public static void generateMethodBody( @NotNull MethodVisitor mv, @NotNull FunctionDescriptor functionDescriptor, @NotNull MethodContext context, @NotNull JvmMethodSignature signature, @NotNull FunctionGenerationStrategy strategy, @NotNull MemberCodegen<?> parentCodegen) { mv.visitCode(); Label methodBegin = new Label(); mv.visitLabel(methodBegin); JetTypeMapper typeMapper = parentCodegen.typeMapper; Label methodEnd; if (context.getParentContext() instanceof DelegatingFacadeContext) { generateFacadeDelegateMethodBody( mv, signature.getAsmMethod(), (DelegatingFacadeContext) context.getParentContext()); methodEnd = new Label(); } else { FrameMap frameMap = createFrameMap( parentCodegen.state, functionDescriptor, signature, isStaticMethod(context.getContextKind(), functionDescriptor)); Label methodEntry = new Label(); mv.visitLabel(methodEntry); context.setMethodStartLabel(methodEntry); if (!JetTypeMapper.isAccessor(functionDescriptor)) { genNotNullAssertionsForParameters( new InstructionAdapter(mv), parentCodegen.state, functionDescriptor, frameMap); } methodEnd = new Label(); context.setMethodEndLabel(methodEnd); strategy.generateBody(mv, frameMap, signature, context, parentCodegen); } mv.visitLabel(methodEnd); Type thisType = getThisTypeForFunction(functionDescriptor, context, typeMapper); generateLocalVariableTable( mv, signature, functionDescriptor, thisType, methodBegin, methodEnd, context.getContextKind()); }
private SMAP generateMethodBody( @NotNull MethodVisitor adapter, @NotNull FunctionDescriptor descriptor, @NotNull MethodContext context, @NotNull JetExpression expression, @NotNull JvmMethodSignature jvmMethodSignature, boolean isLambda) { FakeMemberCodegen parentCodegen = new FakeMemberCodegen( codegen.getParentCodegen(), expression, (FieldOwnerContext) context.getParentContext(), isLambda ? codegen.getParentCodegen().getClassName() : typeMapper.mapOwner(descriptor).getInternalName()); FunctionGenerationStrategy strategy = expression instanceof JetCallableReferenceExpression ? new FunctionReferenceGenerationStrategy( state, descriptor, CallUtilKt.getResolvedCallWithAssert( ((JetCallableReferenceExpression) expression).getCallableReference(), codegen.getBindingContext())) : new FunctionGenerationStrategy.FunctionDefault( state, descriptor, (JetDeclarationWithBody) expression); FunctionCodegen.generateMethodBody( adapter, descriptor, context, jvmMethodSignature, strategy, // Wrapping for preventing marking actual parent codegen as containing reifier markers parentCodegen); return createSMAPWithDefaultMapping( expression, parentCodegen.getOrCreateSourceMapper().getResultMappings()); }
@NotNull private SMAPAndMethodNode createMethodNode(boolean callDefault) throws ClassNotFoundException, IOException { JvmMethodSignature jvmSignature = typeMapper.mapSignature(functionDescriptor, context.getContextKind()); Method asmMethod; if (callDefault) { asmMethod = typeMapper.mapDefaultMethod(functionDescriptor, context.getContextKind()); } else { asmMethod = jvmSignature.getAsmMethod(); } SMAPAndMethodNode nodeAndSMAP; if (functionDescriptor instanceof DeserializedSimpleFunctionDescriptor) { JetTypeMapper.ContainingClassesInfo containingClasses = typeMapper.getContainingClassesForDeserializedCallable( (DeserializedSimpleFunctionDescriptor) functionDescriptor); VirtualFile file = InlineCodegenUtil.getVirtualFileForCallable(containingClasses.getImplClassId(), state); nodeAndSMAP = InlineCodegenUtil.getMethodNode( file.contentsToByteArray(), asmMethod.getName(), asmMethod.getDescriptor(), containingClasses.getFacadeClassId()); if (nodeAndSMAP == null) { throw new RuntimeException( "Couldn't obtain compiled function body for " + descriptorName(functionDescriptor)); } } else { PsiElement element = DescriptorToSourceUtils.descriptorToDeclaration(functionDescriptor); if (element == null || !(element instanceof JetNamedFunction)) { throw new RuntimeException( "Couldn't find declaration for function " + descriptorName(functionDescriptor)); } JetNamedFunction inliningFunction = (JetNamedFunction) element; MethodNode node = new MethodNode( InlineCodegenUtil.API, getMethodAsmFlags(functionDescriptor, context.getContextKind()) | (callDefault ? Opcodes.ACC_STATIC : 0), asmMethod.getName(), asmMethod.getDescriptor(), jvmSignature.getGenericsSignature(), null); // for maxLocals calculation MethodVisitor maxCalcAdapter = InlineCodegenUtil.wrapWithMaxLocalCalc(node); MethodContext methodContext = context.getParentContext().intoFunction(functionDescriptor); SMAP smap; if (callDefault) { Type implementationOwner = typeMapper.mapOwner(functionDescriptor); FakeMemberCodegen parentCodegen = new FakeMemberCodegen( codegen.getParentCodegen(), inliningFunction, (FieldOwnerContext) methodContext.getParentContext(), implementationOwner.getInternalName()); FunctionCodegen.generateDefaultImplBody( methodContext, functionDescriptor, maxCalcAdapter, DefaultParameterValueLoader.DEFAULT, inliningFunction, parentCodegen); smap = createSMAPWithDefaultMapping( inliningFunction, parentCodegen.getOrCreateSourceMapper().getResultMappings()); } else { smap = generateMethodBody( maxCalcAdapter, functionDescriptor, methodContext, inliningFunction, jvmSignature, false); } nodeAndSMAP = new SMAPAndMethodNode(node, smap); maxCalcAdapter.visitMaxs(-1, -1); maxCalcAdapter.visitEnd(); } return nodeAndSMAP; }
public static void generateMethodBody( @NotNull MethodVisitor mv, @NotNull FunctionDescriptor functionDescriptor, @NotNull MethodContext context, @NotNull JvmMethodSignature signature, @NotNull FunctionGenerationStrategy strategy, @NotNull MemberCodegen<?> parentCodegen) { mv.visitCode(); Label methodBegin = new Label(); mv.visitLabel(methodBegin); JetTypeMapper typeMapper = parentCodegen.typeMapper; if (BuiltinSpecialBridgesUtil.shouldHaveTypeSafeBarrier( functionDescriptor, getSignatureMapper(typeMapper))) { generateTypeCheckBarrierIfNeeded( new InstructionAdapter(mv), functionDescriptor, signature.getReturnType(), /* delegateParameterType = */ null); } Label methodEnd; int functionFakeIndex = -1; int lambdaFakeIndex = -1; if (context.getParentContext() instanceof MultifileClassFacadeContext) { generateFacadeDelegateMethodBody( mv, signature.getAsmMethod(), (MultifileClassFacadeContext) context.getParentContext()); methodEnd = new Label(); } else { FrameMap frameMap = createFrameMap( parentCodegen.state, functionDescriptor, signature, isStaticMethod(context.getContextKind(), functionDescriptor)); if (context.isInlineMethodContext()) { functionFakeIndex = frameMap.enterTemp(Type.INT_TYPE); } if (context instanceof InlineLambdaContext) { lambdaFakeIndex = frameMap.enterTemp(Type.INT_TYPE); } Label methodEntry = new Label(); mv.visitLabel(methodEntry); context.setMethodStartLabel(methodEntry); if (!JetTypeMapper.isAccessor(functionDescriptor)) { genNotNullAssertionsForParameters( new InstructionAdapter(mv), parentCodegen.state, functionDescriptor, frameMap); } methodEnd = new Label(); context.setMethodEndLabel(methodEnd); strategy.generateBody(mv, frameMap, signature, context, parentCodegen); } mv.visitLabel(methodEnd); Type thisType = getThisTypeForFunction(functionDescriptor, context, typeMapper); generateLocalVariableTable( mv, signature, functionDescriptor, thisType, methodBegin, methodEnd, context.getContextKind()); if (context.isInlineMethodContext() && functionFakeIndex != -1) { mv.visitLocalVariable( JvmAbi.LOCAL_VARIABLE_NAME_PREFIX_INLINE_FUNCTION + functionDescriptor.getName().asString(), Type.INT_TYPE.getDescriptor(), null, methodBegin, methodEnd, functionFakeIndex); } if (context instanceof InlineLambdaContext && thisType != null && lambdaFakeIndex != -1) { String name = thisType.getClassName(); int indexOfLambdaOrdinal = name.lastIndexOf("$"); if (indexOfLambdaOrdinal > 0) { int lambdaOrdinal = Integer.parseInt(name.substring(indexOfLambdaOrdinal + 1)); mv.visitLocalVariable( JvmAbi.LOCAL_VARIABLE_NAME_PREFIX_INLINE_ARGUMENT + lambdaOrdinal, Type.INT_TYPE.getDescriptor(), null, methodBegin, methodEnd, lambdaFakeIndex); } } }