use of org.jetbrains.org.objectweb.asm.Type in project kotlin by JetBrains.
the class KotlinTypeMapper method writeAdditionalConstructorParameters.
private void writeAdditionalConstructorParameters(@NotNull ClassConstructorDescriptor descriptor, @NotNull JvmSignatureWriter sw) {
boolean isSynthesized = descriptor.getKind() == CallableMemberDescriptor.Kind.SYNTHESIZED;
//if (isSynthesized) return;
MutableClosure closure = bindingContext.get(CodegenBinding.CLOSURE, descriptor.getContainingDeclaration());
ClassDescriptor captureThis = getDispatchReceiverParameterForConstructorCall(descriptor, closure);
if (!isSynthesized && captureThis != null) {
writeParameter(sw, JvmMethodParameterKind.OUTER, captureThis.getDefaultType(), descriptor);
}
KotlinType captureReceiverType = closure != null ? closure.getCaptureReceiverType() : null;
if (captureReceiverType != null) {
writeParameter(sw, JvmMethodParameterKind.RECEIVER, captureReceiverType, descriptor);
}
ClassDescriptor containingDeclaration = descriptor.getContainingDeclaration();
if (!isSynthesized) {
if (containingDeclaration.getKind() == ClassKind.ENUM_CLASS || containingDeclaration.getKind() == ClassKind.ENUM_ENTRY) {
writeParameter(sw, JvmMethodParameterKind.ENUM_NAME_OR_ORDINAL, DescriptorUtilsKt.getBuiltIns(descriptor).getStringType(), descriptor);
writeParameter(sw, JvmMethodParameterKind.ENUM_NAME_OR_ORDINAL, DescriptorUtilsKt.getBuiltIns(descriptor).getIntType(), descriptor);
}
}
if (closure == null)
return;
for (DeclarationDescriptor variableDescriptor : closure.getCaptureVariables().keySet()) {
Type type;
if (variableDescriptor instanceof VariableDescriptor && !(variableDescriptor instanceof PropertyDescriptor)) {
Type sharedVarType = getSharedVarType(variableDescriptor);
if (sharedVarType == null) {
if (isDelegatedLocalVariable(variableDescriptor)) {
VariableDescriptor delegateVariableDescriptor = bindingContext.get(LOCAL_VARIABLE_DELEGATE, (VariableDescriptor) variableDescriptor);
assert delegateVariableDescriptor != null : "Local delegated property " + variableDescriptor + " delegate descriptor should be not null";
sharedVarType = mapType(delegateVariableDescriptor.getType());
} else {
sharedVarType = mapType(((VariableDescriptor) variableDescriptor).getType());
}
}
type = sharedVarType;
} else if (isLocalFunction(variableDescriptor)) {
//noinspection CastConflictsWithInstanceof
type = asmTypeForAnonymousClass(bindingContext, (FunctionDescriptor) variableDescriptor);
} else {
type = null;
}
if (type != null) {
closure.setCapturedParameterOffsetInConstructor(variableDescriptor, sw.getCurrentSignatureSize() + 1);
writeParameter(sw, JvmMethodParameterKind.CAPTURED_LOCAL_VARIABLE, type);
}
}
// because such classes are not accessible from the outside world
if (classBuilderMode.generateBodies) {
ResolvedCall<ConstructorDescriptor> superCall = findFirstDelegatingSuperCall(descriptor);
if (superCall == null)
return;
writeSuperConstructorCallParameters(sw, descriptor, superCall, captureThis != null);
}
}
use of org.jetbrains.org.objectweb.asm.Type in project kotlin by JetBrains.
the class EnumSwitchCodegen method generateSubject.
@Override
protected void generateSubject() {
codegen.getState().getMappingsClassesForWhenByEnum().generateMappingsClassForExpression(expression);
super.generateSubject();
generateNullCheckIfNeeded();
v.getstatic(mapping.getMappingsClassInternalName(), mapping.getFieldName(), MappingClassesForWhenByEnumCodegen.MAPPINGS_FIELD_DESCRIPTOR);
v.swap();
Type enumType = codegen.getState().getTypeMapper().mapClass(mapping.getEnumClassDescriptor());
v.invokevirtual(enumType.getInternalName(), "ordinal", Type.getMethodDescriptor(Type.INT_TYPE), false);
v.aload(Type.INT_TYPE);
}
use of org.jetbrains.org.objectweb.asm.Type in project kotlin by JetBrains.
the class InlineCodegen method recordParameterValueInLocalVal.
private Runnable recordParameterValueInLocalVal(boolean delayedWritingToLocals, @NotNull final ParameterInfo... infos) {
final int[] index = new int[infos.length];
for (int i = 0; i < infos.length; i++) {
ParameterInfo info = infos[i];
if (!info.isSkippedOrRemapped()) {
index[i] = codegen.getFrameMap().enterTemp(info.getType());
} else {
index[i] = -1;
}
}
Runnable runnable = new Runnable() {
@Override
public void run() {
for (int i = infos.length - 1; i >= 0; i--) {
ParameterInfo info = infos[i];
if (!info.isSkippedOrRemapped()) {
Type type = info.type;
StackValue.Local local = StackValue.local(index[i], type);
local.store(StackValue.onStack(type), codegen.v);
if (info instanceof CapturedParamInfo) {
info.setRemapValue(local);
((CapturedParamInfo) info).setSynthetic(true);
}
}
}
}
};
if (delayedWritingToLocals)
return runnable;
runnable.run();
return null;
}
use of org.jetbrains.org.objectweb.asm.Type in project kotlin by JetBrains.
the class InternalFinallyBlockInliner method processInlineFunFinallyBlocks.
private void processInlineFunFinallyBlocks() {
int nextTempNonLocalVarIndex = initAndGetVarIndexForNonLocalReturnValue();
InsnList instructions = inlineFun.instructions;
//As we do finally block code search after non-local return instruction
// we should be sure that all others non-local returns already processed in this finally block.
// So we do instruction processing in reverse order!
AbstractInsnNode curIns = instructions.getLast();
while (curIns != null) {
processInstruction(curIns, false);
//At this point only global return is possible, local one already substituted with: goto endLabel
if (!InlineCodegenUtil.isReturnOpcode(curIns.getOpcode()) || !InlineCodegenUtil.isMarkedReturn(curIns)) {
curIns = curIns.getPrevious();
continue;
}
List<TryCatchBlockNodeInfo> currentCoveringNodesFromInnermost = sortTryCatchBlocks(new ArrayList<TryCatchBlockNodeInfo>(getTryBlocksMetaInfo().getCurrentIntervals()));
checkCoveringBlocksInvariant(Lists.reverse(currentCoveringNodesFromInnermost));
if (currentCoveringNodesFromInnermost.isEmpty() || currentCoveringNodesFromInnermost.get(currentCoveringNodesFromInnermost.size() - 1).getOnlyCopyNotProcess()) {
curIns = curIns.getPrevious();
continue;
}
AbstractInsnNode markedReturn = curIns;
AbstractInsnNode instrInsertFinallyBefore = markedReturn.getPrevious();
AbstractInsnNode nextPrev = instrInsertFinallyBefore.getPrevious();
assert markedReturn.getNext() instanceof LabelNode : "Label should be occurred after non-local return";
LabelNode newFinallyEnd = (LabelNode) markedReturn.getNext();
Type nonLocalReturnType = InlineCodegenUtil.getReturnType(markedReturn.getOpcode());
//Generally there could be several tryCatch blocks (group) on one code interval (same start and end labels, but maybe different handlers) -
// all of them refer to one try/*catches*/finally or try/catches.
// Each group that corresponds to try/*catches*/finally contains tryCatch block with default handler.
// For each such group we should insert corresponding finally before non-local return.
// So we split all try blocks on current instructions to groups and process them independently
List<TryBlockCluster<TryCatchBlockNodeInfo>> clustersFromInnermost = TryBlockClusteringKt.doClustering(currentCoveringNodesFromInnermost);
Iterator<TryBlockCluster<TryCatchBlockNodeInfo>> tryCatchBlockIterator = clustersFromInnermost.iterator();
checkClusterInvariant(clustersFromInnermost);
int originalDepthIndex = 0;
while (tryCatchBlockIterator.hasNext()) {
TryBlockCluster<TryCatchBlockNodeInfo> clusterToFindFinally = tryCatchBlockIterator.next();
List<TryCatchBlockNodeInfo> clusterBlocks = clusterToFindFinally.getBlocks();
TryCatchBlockNodeInfo nodeWithDefaultHandlerIfExists = clusterBlocks.get(clusterBlocks.size() - 1);
FinallyBlockInfo finallyInfo = findFinallyBlockBody(nodeWithDefaultHandlerIfExists, getTryBlocksMetaInfo().getAllIntervals());
if (finallyInfo == null)
continue;
if (nodeWithDefaultHandlerIfExists.getOnlyCopyNotProcess()) {
//so it's a gap in try/catch handlers
throw new RuntimeException("Lambda try blocks should be skipped");
}
originalDepthIndex++;
instructions.resetLabels();
List<TryCatchBlockNodePosition> tryCatchBlockInlinedInFinally = findTryCatchBlocksInlinedInFinally(finallyInfo);
//Creating temp node for finally block copy with some additional instruction
MethodNode finallyBlockCopy = createEmptyMethodNode();
Label newFinallyStart = new Label();
Label insertedBlockEnd = new Label();
boolean generateAloadAstore = nonLocalReturnType != Type.VOID_TYPE && !finallyInfo.isEmpty();
if (generateAloadAstore) {
finallyBlockCopy.visitVarInsn(nonLocalReturnType.getOpcode(Opcodes.ISTORE), nextTempNonLocalVarIndex);
}
finallyBlockCopy.visitLabel(newFinallyStart);
//Keep some information about label nodes, we need it to understand whether it's jump inside finally block or outside
// in first case we do call VISIT on instruction otherwise recreating jump instruction (see below)
Set<LabelNode> labelsInsideFinally = rememberOriginalLabelNodes(finallyInfo);
//Writing finally block body to temporary node
AbstractInsnNode currentIns = finallyInfo.startIns;
while (currentIns != finallyInfo.endInsExclusive) {
boolean isInsOrJumpInsideFinally = !(currentIns instanceof JumpInsnNode) || labelsInsideFinally.contains(((JumpInsnNode) currentIns).label);
copyInstruction(finallyBlockCopy, currentIns, isInsOrJumpInsideFinally, originalDepthIndex);
currentIns = currentIns.getNext();
}
if (generateAloadAstore) {
finallyBlockCopy.visitVarInsn(nonLocalReturnType.getOpcode(Opcodes.ILOAD), nextTempNonLocalVarIndex);
//TODO: do more wise indexing
nextTempNonLocalVarIndex += nonLocalReturnType.getSize();
}
finallyBlockCopy.visitLabel(insertedBlockEnd);
//Copying finally body before non-local return instruction
InlineCodegenUtil.insertNodeBefore(finallyBlockCopy, inlineFun, instrInsertFinallyBefore);
updateExceptionTable(clusterBlocks, newFinallyStart, newFinallyEnd, tryCatchBlockInlinedInFinally, labelsInsideFinally, (LabelNode) insertedBlockEnd.info);
}
//skip just inserted finally
curIns = markedReturn.getPrevious();
while (curIns != null && curIns != nextPrev) {
processInstruction(curIns, false);
curIns = curIns.getPrevious();
}
//finally block inserted so we need split update localVarTable in lambda
if (instrInsertFinallyBefore.getPrevious() != nextPrev && curIns != null) {
LabelNode startNode = new LabelNode();
LabelNode endNode = new LabelNode();
instructions.insert(curIns, startNode);
//TODO: note that on return expression we have no variables
instructions.insert(markedReturn, endNode);
getLocalVarsMetaInfo().splitCurrentIntervals(new SimpleInterval(startNode, endNode), true);
}
}
substituteTryBlockNodes(inlineFun);
substituteLocalVarTable(inlineFun);
}
use of org.jetbrains.org.objectweb.asm.Type in project kotlin by JetBrains.
the class LambdaInfo method getCapturedVars.
@NotNull
public List<CapturedParamDesc> getCapturedVars() {
//lazy initialization cause it would be calculated after object creation
if (capturedVars == null) {
capturedVars = new ArrayList<CapturedParamDesc>();
if (closure.getCaptureThis() != null) {
Type type = typeMapper.mapType(closure.getCaptureThis());
EnclosedValueDescriptor descriptor = new EnclosedValueDescriptor(AsmUtil.CAPTURED_THIS_FIELD, /* descriptor = */
null, StackValue.field(type, closureClassType, AsmUtil.CAPTURED_THIS_FIELD, false, StackValue.LOCAL_0), type);
capturedVars.add(getCapturedParamInfo(descriptor));
}
if (closure.getCaptureReceiverType() != null) {
Type type = typeMapper.mapType(closure.getCaptureReceiverType());
EnclosedValueDescriptor descriptor = new EnclosedValueDescriptor(AsmUtil.CAPTURED_RECEIVER_FIELD, /* descriptor = */
null, StackValue.field(type, closureClassType, AsmUtil.CAPTURED_RECEIVER_FIELD, false, StackValue.LOCAL_0), type);
capturedVars.add(getCapturedParamInfo(descriptor));
}
for (EnclosedValueDescriptor descriptor : closure.getCaptureVariables().values()) {
capturedVars.add(getCapturedParamInfo(descriptor));
}
}
return capturedVars;
}
Aggregations