private void generateConstInstance() { MethodVisitor mv = v.newMethod( OtherOrigin(element, funDescriptor), ACC_STATIC | ACC_SYNTHETIC, "<clinit>", "()V", null, ArrayUtil.EMPTY_STRING_ARRAY); InstructionAdapter iv = new InstructionAdapter(mv); v.newField( OtherOrigin(element, funDescriptor), ACC_STATIC | ACC_FINAL | ACC_PUBLIC, JvmAbi.INSTANCE_FIELD, asmType.getDescriptor(), null, null); if (state.getClassBuilderMode() == ClassBuilderMode.FULL) { mv.visitCode(); iv.anew(asmType); iv.dup(); iv.invokespecial(asmType.getInternalName(), "<init>", "()V", false); iv.putstatic(asmType.getInternalName(), JvmAbi.INSTANCE_FIELD, asmType.getDescriptor()); mv.visitInsn(RETURN); FunctionCodegen.endVisit(mv, "<clinit>", element); } }
private void generateBridge( @Nullable PsiElement origin, @NotNull FunctionDescriptor descriptor, @NotNull Method bridge, @NotNull Method delegateTo, boolean isSpecialBridge, boolean isStubDeclarationWithDelegationToSuper) { boolean isSpecialOrDelegationToSuper = isSpecialBridge || isStubDeclarationWithDelegationToSuper; int flags = ACC_PUBLIC | ACC_BRIDGE | (!isSpecialOrDelegationToSuper ? ACC_SYNTHETIC : 0) | (isSpecialBridge ? ACC_FINAL : 0); // TODO. MethodVisitor mv = v.newMethod( JvmDeclarationOriginKt.Bridge(descriptor, origin), flags, bridge.getName(), bridge.getDescriptor(), null, null); if (state.getClassBuilderMode() != ClassBuilderMode.FULL) return; mv.visitCode(); Type[] argTypes = bridge.getArgumentTypes(); Type[] originalArgTypes = delegateTo.getArgumentTypes(); InstructionAdapter iv = new InstructionAdapter(mv); MemberCodegen.markLineNumberForDescriptor(owner.getThisDescriptor(), iv); if (delegateTo.getArgumentTypes().length == 1 && isSpecialBridge) { generateTypeCheckBarrierIfNeeded( iv, descriptor, bridge.getReturnType(), delegateTo.getArgumentTypes()[0]); } iv.load(0, OBJECT_TYPE); for (int i = 0, reg = 1; i < argTypes.length; i++) { StackValue.local(reg, argTypes[i]).put(originalArgTypes[i], iv); //noinspection AssignmentToForLoopParameter reg += argTypes[i].getSize(); } if (isStubDeclarationWithDelegationToSuper) { ClassDescriptor parentClass = getSuperClassDescriptor((ClassDescriptor) descriptor.getContainingDeclaration()); assert parentClass != null; String parentInternalName = typeMapper.mapClass(parentClass).getInternalName(); iv.invokespecial(parentInternalName, delegateTo.getName(), delegateTo.getDescriptor()); } else { iv.invokevirtual(v.getThisName(), delegateTo.getName(), delegateTo.getDescriptor()); } StackValue.coerce(delegateTo.getReturnType(), bridge.getReturnType(), iv); iv.areturn(bridge.getReturnType()); endVisit(mv, "bridge method", origin); }
public static void generateFinallyMarker( @NotNull InstructionAdapter v, int depth, boolean start) { v.iconst(depth); v.invokestatic( INLINE_MARKER_CLASS_NAME, start ? INLINE_MARKER_FINALLY_START : INLINE_MARKER_FINALLY_END, "(I)V", false); }
public static void addInlineMarker(@NotNull InstructionAdapter v, boolean isStartNotEnd) { v.visitMethodInsn( Opcodes.INVOKESTATIC, INLINE_MARKER_CLASS_NAME, (isStartNotEnd ? INLINE_MARKER_BEFORE_METHOD_NAME : INLINE_MARKER_AFTER_METHOD_NAME), "()V", false); }
private void generateBridge(@NotNull Method bridge, @NotNull Method delegate) { if (bridge.equals(delegate)) return; MethodVisitor mv = v.newMethod( OtherOrigin(element, funDescriptor), ACC_PUBLIC | ACC_BRIDGE, bridge.getName(), bridge.getDescriptor(), null, ArrayUtil.EMPTY_STRING_ARRAY); if (state.getClassBuilderMode() != ClassBuilderMode.FULL) return; mv.visitCode(); InstructionAdapter iv = new InstructionAdapter(mv); ImplementationBodyCodegen.markLineNumberForSyntheticFunction( DescriptorUtils.getParentOfType(funDescriptor, ClassDescriptor.class), iv); iv.load(0, asmType); ReceiverParameterDescriptor receiver = funDescriptor.getExtensionReceiverParameter(); int count = 1; if (receiver != null) { StackValue.local(count, bridge.getArgumentTypes()[count - 1]) .put(typeMapper.mapType(receiver.getType()), iv); count++; } List<ValueParameterDescriptor> params = funDescriptor.getValueParameters(); for (ValueParameterDescriptor param : params) { StackValue.local(count, bridge.getArgumentTypes()[count - 1]) .put(typeMapper.mapType(param.getType()), iv); count++; } iv.invokevirtual( asmType.getInternalName(), delegate.getName(), delegate.getDescriptor(), false); StackValue.onStack(delegate.getReturnType()).put(bridge.getReturnType(), iv); iv.areturn(bridge.getReturnType()); FunctionCodegen.endVisit(mv, "bridge", element); }
private static void genDefaultSuperCallCheckIfNeeded( @NotNull InstructionAdapter iv, @NotNull Method defaultMethod) { String defaultMethodName = defaultMethod.getName(); if ("<init>".equals(defaultMethodName)) { return; } Label end = new Label(); int handleIndex = (Type.getArgumentsAndReturnSizes(defaultMethod.getDescriptor()) >> 2) - 2; /*-1 for this, and -1 for handle*/ iv.load(handleIndex, OBJECT_TYPE); iv.ifnull(end); AsmUtil.genThrow( iv, "java/lang/UnsupportedOperationException", "Super calls with default arguments not supported in this target, function: " + StringsKt.substringBeforeLast( defaultMethodName, JvmAbi.DEFAULT_PARAMS_IMPL_SUFFIX, defaultMethodName)); iv.visitLabel(end); }
private static void generateTypeCheckBarrierIfNeeded( @NotNull InstructionAdapter iv, @NotNull FunctionDescriptor descriptor, @NotNull Type returnType, @Nullable final Type delegateParameterType) { BuiltinMethodsWithSpecialGenericSignature.DefaultValue defaultValue = BuiltinMethodsWithSpecialGenericSignature.getDefaultValueForOverriddenBuiltinFunction( descriptor); if (defaultValue == null) return; assert descriptor.getValueParameters().size() == 1 : "Should be descriptor with one value parameter, but found: " + descriptor; boolean isCheckForAny = delegateParameterType == null || OBJECT_TYPE.equals(delegateParameterType); final KotlinType kotlinType = descriptor.getValueParameters().get(0).getType(); if (isCheckForAny && TypeUtils.isNullableType(kotlinType)) return; iv.load(1, OBJECT_TYPE); Label afterBarrier = new Label(); if (isCheckForAny) { assert !TypeUtils.isNullableType(kotlinType) : "Only bridges for not-nullable types are necessary"; iv.ifnonnull(afterBarrier); } else { CodegenUtilKt.generateIsCheck(iv, kotlinType, boxType(delegateParameterType)); iv.ifne(afterBarrier); } StackValue.constant(defaultValue.getValue(), returnType).put(returnType, iv); iv.areturn(returnType); iv.visitLabel(afterBarrier); }
private static void equipFunctionReferenceWithReflection( @NotNull InstructionAdapter v, @NotNull FunctionDescriptor target) { DeclarationDescriptor container = target.getContainingDeclaration(); Type type; if (container instanceof PackageFragmentDescriptor) { type = target.getExtensionReceiverParameter() != null ? K_TOP_LEVEL_EXTENSION_FUNCTION : K_TOP_LEVEL_FUNCTION; } else if (container instanceof ClassDescriptor) { type = K_MEMBER_FUNCTION; } else { type = K_LOCAL_FUNCTION; } Method method = method("function", K_FUNCTION, FUNCTION_REFERENCE); v.invokestatic(REFLECTION, method.getName(), method.getDescriptor(), false); StackValue.coerce(K_FUNCTION, type, v); }
public static void putStackValuesIntoLocals( List<Type> directOrder, int shift, InstructionAdapter iv, String descriptor) { Type[] actualParams = Type.getArgumentTypes(descriptor); assert actualParams.length == directOrder.size() : "Number of expected and actual params should be equals!"; int size = 0; for (Type next : directOrder) { size += next.getSize(); } shift += size; int index = directOrder.size(); for (Type next : Lists.reverse(directOrder)) { shift -= next.getSize(); Type typeOnStack = actualParams[--index]; if (!typeOnStack.equals(next)) { StackValue.onStack(typeOnStack).put(next, iv); } iv.store(shift, next); } }
public void visitVarInsn(int opcode, int var, InstructionAdapter mv) { RemapInfo remapInfo = remap(var); StackValue value = remapInfo.value; if (value instanceof StackValue.Local) { if (remapInfo.parameterInfo != null) { // All remapped value parameters can't be rewritten except case of default ones. // On remapping default parameter to actual value there is only one instruction that writes // to it according to mask value // but if such parameter remapped then it passed and this mask branch code never executed // TODO add assertion about parameter default value: descriptor is required opcode = value.type.getOpcode( InlineCodegenUtil.isStoreInstruction(opcode) ? Opcodes.ISTORE : Opcodes.ILOAD); } mv.visitVarInsn(opcode, ((StackValue.Local) value).index); if (remapInfo.parameterInfo != null) { StackValue.coerce(value.type, remapInfo.parameterInfo.type, mv); } } else { assert remapInfo.parameterInfo != null : "Non local value should have parameter info"; value.put(remapInfo.parameterInfo.type, mv); } }
@NotNull private Method generateConstructor(@NotNull Type superClassAsmType) { List<FieldInfo> args = calculateConstructorParameters(typeMapper, closure, asmType); Type[] argTypes = fieldListToTypeArray(args); Method constructor = new Method("<init>", Type.VOID_TYPE, argTypes); MethodVisitor mv = v.newMethod( OtherOrigin(element, funDescriptor), visibilityFlag, "<init>", constructor.getDescriptor(), null, ArrayUtil.EMPTY_STRING_ARRAY); if (state.getClassBuilderMode() == ClassBuilderMode.FULL) { mv.visitCode(); InstructionAdapter iv = new InstructionAdapter(mv); int k = 1; for (FieldInfo fieldInfo : args) { k = genAssignInstanceFieldFromParam(fieldInfo, k, iv); } iv.load(0, superClassAsmType); if (superClassAsmType.equals(LAMBDA) || superClassAsmType.equals(FUNCTION_REFERENCE)) { int arity = funDescriptor.getValueParameters().size(); if (funDescriptor.getExtensionReceiverParameter() != null) arity++; if (funDescriptor.getDispatchReceiverParameter() != null) arity++; iv.iconst(arity); iv.invokespecial(superClassAsmType.getInternalName(), "<init>", "(I)V", false); } else { iv.invokespecial(superClassAsmType.getInternalName(), "<init>", "()V", false); } iv.visitInsn(RETURN); FunctionCodegen.endVisit(iv, "constructor", element); } return constructor; }
private static void generateDelegateToMethodBody( boolean isStatic, @NotNull MethodVisitor mv, @NotNull Method asmMethod, @NotNull String classToDelegateTo) { InstructionAdapter iv = new InstructionAdapter(mv); Type[] argTypes = asmMethod.getArgumentTypes(); // The first line of some package file is written to the line number attribute of a static // delegate to allow to 'step into' it // This is similar to what javac does with bridge methods Label label = new Label(); iv.visitLabel(label); iv.visitLineNumber(1, label); int k = isStatic ? 0 : 1; for (Type argType : argTypes) { iv.load(k, argType); k += argType.getSize(); } iv.invokestatic(classToDelegateTo, asmMethod.getName(), asmMethod.getDescriptor(), false); iv.areturn(asmMethod.getReturnType()); }
public static void generateDefaultImplBody( @NotNull MethodContext methodContext, @NotNull FunctionDescriptor functionDescriptor, @NotNull MethodVisitor mv, @NotNull DefaultParameterValueLoader loadStrategy, @Nullable KtNamedFunction function, @NotNull MemberCodegen<?> parentCodegen, @NotNull Method defaultMethod) { GenerationState state = parentCodegen.state; JvmMethodSignature signature = state.getTypeMapper().mapSignature(functionDescriptor, methodContext.getContextKind()); boolean isStatic = isStaticMethod(methodContext.getContextKind(), functionDescriptor); FrameMap frameMap = createFrameMap(state, functionDescriptor, signature, isStatic); ExpressionCodegen codegen = new ExpressionCodegen( mv, frameMap, signature.getReturnType(), methodContext, state, parentCodegen); CallGenerator generator = codegen.getOrCreateCallGeneratorForDefaultImplBody(functionDescriptor, function); InstructionAdapter iv = new InstructionAdapter(mv); genDefaultSuperCallCheckIfNeeded(iv, defaultMethod); loadExplicitArgumentsOnStack(OBJECT_TYPE, isStatic, signature, generator); List<JvmMethodParameterSignature> mappedParameters = signature.getValueParameters(); int capturedArgumentsCount = 0; while (capturedArgumentsCount < mappedParameters.size() && mappedParameters.get(capturedArgumentsCount).getKind() != JvmMethodParameterKind.VALUE) { capturedArgumentsCount++; } int maskIndex = 0; List<ValueParameterDescriptor> valueParameters = functionDescriptor.getValueParameters(); for (int index = 0; index < valueParameters.size(); index++) { if (index % Integer.SIZE == 0) { maskIndex = frameMap.enterTemp(Type.INT_TYPE); } ValueParameterDescriptor parameterDescriptor = valueParameters.get(index); Type type = mappedParameters.get(capturedArgumentsCount + index).getAsmType(); int parameterIndex = frameMap.getIndex(parameterDescriptor); if (parameterDescriptor.declaresDefaultValue()) { iv.load(maskIndex, Type.INT_TYPE); iv.iconst(1 << (index % Integer.SIZE)); iv.and(Type.INT_TYPE); Label loadArg = new Label(); iv.ifeq(loadArg); StackValue.local(parameterIndex, type) .store(loadStrategy.genValue(parameterDescriptor, codegen), iv); iv.mark(loadArg); } generator.putValueIfNeeded(type, StackValue.local(parameterIndex, type)); } CallableMethod method = state.getTypeMapper().mapToCallableMethod(functionDescriptor, false); generator.genCallWithoutAssertions(method, codegen); iv.areturn(signature.getReturnType()); }
public static void generateGlobalReturnFlag( @NotNull InstructionAdapter iv, @NotNull String labelName) { iv.invokestatic(NON_LOCAL_RETURN, labelName, "()V", false); }
protected void generatePropertyMetadataArrayFieldIfNeeded(@NotNull Type thisAsmType) { List<JetProperty> delegatedProperties = new ArrayList<JetProperty>(); for (JetDeclaration declaration : ((JetDeclarationContainer) element).getDeclarations()) { if (declaration instanceof JetProperty) { JetProperty property = (JetProperty) declaration; if (property.getDelegate() != null) { delegatedProperties.add(property); } } } if (delegatedProperties.isEmpty()) return; v.newField( null, ACC_PRIVATE | ACC_STATIC | ACC_FINAL | ACC_SYNTHETIC, JvmAbi.PROPERTY_METADATA_ARRAY_NAME, "[" + PROPERTY_METADATA_TYPE, null, null); InstructionAdapter iv = createOrGetClInitCodegen().v; iv.iconst(delegatedProperties.size()); iv.newarray(PROPERTY_METADATA_TYPE); for (int i = 0, size = delegatedProperties.size(); i < size; i++) { VariableDescriptor property = BindingContextUtils.getNotNull(bindingContext, VARIABLE, delegatedProperties.get(i)); iv.dup(); iv.iconst(i); iv.anew(PROPERTY_METADATA_IMPL_TYPE); iv.dup(); iv.visitLdcInsn(property.getName().asString()); iv.invokespecial( PROPERTY_METADATA_IMPL_TYPE.getInternalName(), "<init>", "(Ljava/lang/String;)V"); iv.astore(PROPERTY_METADATA_IMPL_TYPE); } iv.putstatic( thisAsmType.getInternalName(), JvmAbi.PROPERTY_METADATA_ARRAY_NAME, "[" + PROPERTY_METADATA_TYPE); }