use of org.jetbrains.org.objectweb.asm.commons.Method in project kotlin by JetBrains.
the class ClosureCodegen method generateKotlinMetadataAnnotation.
@Override
protected void generateKotlinMetadataAnnotation() {
FunctionDescriptor frontendFunDescriptor = CodegenUtilKt.unwrapFrontendVersion(funDescriptor);
FunctionDescriptor freeLambdaDescriptor = createFreeLambdaDescriptor(frontendFunDescriptor);
Method method = v.getSerializationBindings().get(METHOD_FOR_FUNCTION, frontendFunDescriptor);
assert method != null : "No method for " + frontendFunDescriptor;
v.getSerializationBindings().put(METHOD_FOR_FUNCTION, freeLambdaDescriptor, method);
final DescriptorSerializer serializer = DescriptorSerializer.createForLambda(new JvmSerializerExtension(v.getSerializationBindings(), state));
final ProtoBuf.Function functionProto = serializer.functionProto(freeLambdaDescriptor).build();
WriteAnnotationUtilKt.writeKotlinMetadata(v, state, KotlinClassHeader.Kind.SYNTHETIC_CLASS, 0, new Function1<AnnotationVisitor, Unit>() {
@Override
public Unit invoke(AnnotationVisitor av) {
writeAnnotationData(av, serializer, functionProto);
return Unit.INSTANCE;
}
});
}
use of org.jetbrains.org.objectweb.asm.commons.Method in project kotlin by JetBrains.
the class ClosureCodegen method generateConstructor.
@NotNull
protected Method generateConstructor() {
List<FieldInfo> args = calculateConstructorParameters(typeMapper, closure, asmType);
Type[] argTypes = fieldListToTypeArray(args);
Method constructor = new Method("<init>", Type.VOID_TYPE, argTypes);
MethodVisitor mv = v.newMethod(JvmDeclarationOriginKt.OtherOrigin(element, funDescriptor), visibilityFlag, "<init>", constructor.getDescriptor(), null, ArrayUtil.EMPTY_STRING_ARRAY);
if (state.getClassBuilderMode().generateBodies) {
mv.visitCode();
InstructionAdapter iv = new InstructionAdapter(mv);
Pair<Integer, Type> receiverIndexAndType = CallableReferenceUtilKt.generateClosureFieldsInitializationFromParameters(iv, closure, args);
if (shouldHaveBoundReferenceReceiver && receiverIndexAndType == null) {
throw new AssertionError("No bound reference receiver in constructor parameters: " + args);
}
int boundReferenceReceiverParameterIndex = shouldHaveBoundReferenceReceiver ? receiverIndexAndType.getFirst() : -1;
Type boundReferenceReceiverType = shouldHaveBoundReferenceReceiver ? receiverIndexAndType.getSecond() : null;
iv.load(0, superClassAsmType);
String superClassConstructorDescriptor;
if (superClassAsmType.equals(LAMBDA) || superClassAsmType.equals(FUNCTION_REFERENCE) || superClassAsmType.equals(CoroutineCodegenUtilKt.COROUTINE_IMPL_ASM_TYPE)) {
int arity = calculateArity();
iv.iconst(arity);
if (shouldHaveBoundReferenceReceiver) {
CallableReferenceUtilKt.loadBoundReferenceReceiverParameter(iv, boundReferenceReceiverParameterIndex, boundReferenceReceiverType);
superClassConstructorDescriptor = "(ILjava/lang/Object;)V";
} else {
superClassConstructorDescriptor = "(I)V";
}
} else {
assert !shouldHaveBoundReferenceReceiver : "Unexpected bound reference with supertype " + superClassAsmType;
superClassConstructorDescriptor = "()V";
}
iv.invokespecial(superClassAsmType.getInternalName(), "<init>", superClassConstructorDescriptor, false);
iv.visitInsn(RETURN);
FunctionCodegen.endVisit(iv, "constructor", element);
}
return constructor;
}
use of org.jetbrains.org.objectweb.asm.commons.Method in project kotlin by JetBrains.
the class SignaturesPropagationData method getSuperFunctionsForMethod.
private static List<FunctionDescriptor> getSuperFunctionsForMethod(@NotNull JavaMethod method, @NotNull JavaMethodDescriptor autoMethodDescriptor, @NotNull ClassDescriptor containingClass) {
List<FunctionDescriptor> superFunctions = Lists.newArrayList();
// TODO: Add propagation for other kotlin descriptors (KT-3621)
Name name = method.getName();
Method autoSignature = null;
boolean autoMethodContainsVararg = SignaturePropagationUtilKt.containsVarargs(autoMethodDescriptor);
for (KotlinType supertype : containingClass.getTypeConstructor().getSupertypes()) {
Collection<SimpleFunctionDescriptor> superFunctionCandidates = supertype.getMemberScope().getContributedFunctions(name, NoLookupLocation.WHEN_GET_SUPER_MEMBERS);
if (!autoMethodContainsVararg && !SignaturePropagationUtilKt.containsAnyNotTrivialSignature(superFunctionCandidates))
continue;
if (autoSignature == null) {
autoSignature = SIGNATURE_MAPPER.mapToJvmMethodSignature(autoMethodDescriptor);
}
for (FunctionDescriptor candidate : superFunctionCandidates) {
// TODO: remove this continue when KT-15747 is fixed
if (candidate.isSuspend())
continue;
Method candidateSignature = SIGNATURE_MAPPER.mapToJvmMethodSignature(candidate);
if (KotlinToJvmSignatureMapperKt.erasedSignaturesEqualIgnoringReturnTypes(autoSignature, candidateSignature)) {
superFunctions.add(candidate);
}
}
}
// sorting for diagnostic stability
Collections.sort(superFunctions, new Comparator<FunctionDescriptor>() {
@Override
public int compare(@NotNull FunctionDescriptor fun1, @NotNull FunctionDescriptor fun2) {
FqNameUnsafe fqName1 = getFqName(fun1.getContainingDeclaration());
FqNameUnsafe fqName2 = getFqName(fun2.getContainingDeclaration());
return fqName1.asString().compareTo(fqName2.asString());
}
});
return superFunctions;
}
use of org.jetbrains.org.objectweb.asm.commons.Method in project kotlin by JetBrains.
the class MethodInliner method doInline.
@NotNull
private MethodNode doInline(@NotNull MethodNode node) {
final Deque<InvokeCall> currentInvokes = new LinkedList<InvokeCall>(invokeCalls);
final MethodNode resultNode = new MethodNode(node.access, node.name, node.desc, node.signature, null);
final Iterator<TransformationInfo> iterator = transformations.iterator();
final TypeRemapper remapper = TypeRemapper.createFrom(currentTypeMapping);
final RemappingMethodAdapter remappingMethodAdapter = new RemappingMethodAdapter(resultNode.access, resultNode.desc, resultNode, new AsmTypeRemapper(remapper, inliningContext.getRoot().typeParameterMappings == null, result));
final int markerShift = InlineCodegenUtil.calcMarkerShift(parameters, node);
InlineAdapter lambdaInliner = new InlineAdapter(remappingMethodAdapter, parameters.getArgsSizeOnStack(), sourceMapper) {
private TransformationInfo transformationInfo;
private void handleAnonymousObjectRegeneration() {
transformationInfo = iterator.next();
String oldClassName = transformationInfo.getOldClassName();
if (transformationInfo.shouldRegenerate(isSameModule)) {
//TODO: need poping of type but what to do with local funs???
String newClassName = transformationInfo.getNewClassName();
remapper.addMapping(oldClassName, newClassName);
InliningContext childInliningContext = inliningContext.subInlineWithClassRegeneration(inliningContext.nameGenerator, currentTypeMapping, inlineCallSiteInfo);
ObjectTransformer transformer = transformationInfo.createTransformer(childInliningContext, isSameModule);
InlineResult transformResult = transformer.doTransform(nodeRemapper);
result.merge(transformResult);
result.addChangedType(oldClassName, newClassName);
if (inliningContext.isInliningLambda && transformationInfo.canRemoveAfterTransformation()) {
// this class is transformed and original not used so we should remove original one after inlining
result.addClassToRemove(oldClassName);
}
if (transformResult.getReifiedTypeParametersUsages().wereUsedReifiedParameters()) {
ReifiedTypeInliner.putNeedClassReificationMarker(mv);
result.getReifiedTypeParametersUsages().mergeAll(transformResult.getReifiedTypeParametersUsages());
}
} else if (!transformationInfo.getWasAlreadyRegenerated()) {
result.addNotChangedClass(oldClassName);
}
}
@Override
public void anew(@NotNull Type type) {
if (isAnonymousClass(type.getInternalName())) {
handleAnonymousObjectRegeneration();
}
//in case of regenerated transformationInfo type would be remapped to new one via remappingMethodAdapter
super.anew(type);
}
@Override
public void visitMethodInsn(int opcode, String owner, String name, String desc, boolean itf) {
if (/*INLINE_RUNTIME.equals(owner) &&*/
isInvokeOnLambda(owner, name)) {
//TODO add method
assert !currentInvokes.isEmpty();
InvokeCall invokeCall = currentInvokes.remove();
LambdaInfo info = invokeCall.lambdaInfo;
if (info == null) {
//noninlinable lambda
super.visitMethodInsn(opcode, owner, name, desc, itf);
return;
}
//NB: don't inline cause it changes
int valueParamShift = Math.max(getNextLocalIndex(), markerShift);
putStackValuesIntoLocals(info.getInvokeParamsWithoutCaptured(), valueParamShift, this, desc);
if (invokeCall.lambdaInfo.getFunctionDescriptor().getValueParameters().isEmpty()) {
// There won't be no parameters processing and line call can be left without actual instructions.
// Note: if function is called on the line with other instructions like 1 + foo(), 'nop' will still be generated.
visitInsn(Opcodes.NOP);
}
addInlineMarker(this, true);
Parameters lambdaParameters = info.addAllParameters(nodeRemapper);
InlinedLambdaRemapper newCapturedRemapper = new InlinedLambdaRemapper(info.getLambdaClassType().getInternalName(), nodeRemapper, lambdaParameters);
setLambdaInlining(true);
SMAP lambdaSMAP = info.getNode().getClassSMAP();
//noinspection ConstantConditions
SourceMapper mapper = inliningContext.classRegeneration && !inliningContext.isInliningLambda ? new NestedSourceMapper(sourceMapper, lambdaSMAP.getIntervals(), lambdaSMAP.getSourceInfo()) : new InlineLambdaSourceMapper(sourceMapper.getParent(), info.getNode());
MethodInliner inliner = new MethodInliner(info.getNode().getNode(), lambdaParameters, inliningContext.subInlineLambda(info), newCapturedRemapper, true, /*cause all calls in same module as lambda*/
"Lambda inlining " + info.getLambdaClassType().getInternalName(), mapper, inlineCallSiteInfo, null);
LocalVarRemapper remapper = new LocalVarRemapper(lambdaParameters, valueParamShift);
//TODO add skipped this and receiver
InlineResult lambdaResult = inliner.doInline(this.mv, remapper, true, info, invokeCall.finallyDepthShift);
result.mergeWithNotChangeInfo(lambdaResult);
result.getReifiedTypeParametersUsages().mergeAll(lambdaResult.getReifiedTypeParametersUsages());
//return value boxing/unboxing
Method bridge = typeMapper.mapAsmMethod(ClosureCodegen.getErasedInvokeFunction(info.getFunctionDescriptor()));
Method delegate = typeMapper.mapAsmMethod(info.getFunctionDescriptor());
StackValue.onStack(delegate.getReturnType()).put(bridge.getReturnType(), this);
setLambdaInlining(false);
addInlineMarker(this, false);
mapper.endMapping();
if (inlineOnlySmapSkipper != null) {
inlineOnlySmapSkipper.markCallSiteLineNumber(remappingMethodAdapter);
}
} else if (isAnonymousConstructorCall(owner, name)) {
//TODO add proper message
assert transformationInfo instanceof AnonymousObjectTransformationInfo : "<init> call doesn't correspond to object transformation info: " + owner + "." + name + ", info " + transformationInfo;
InliningContext parent = inliningContext.getParent();
boolean shouldRegenerate = transformationInfo.shouldRegenerate(isSameModule);
boolean isContinuation = parent != null && parent.isContinuation();
if (shouldRegenerate || isContinuation) {
assert shouldRegenerate || inlineCallSiteInfo.getOwnerClassName().equals(transformationInfo.getOldClassName()) : "Only coroutines can call their own constructors";
//put additional captured parameters on stack
AnonymousObjectTransformationInfo info = (AnonymousObjectTransformationInfo) transformationInfo;
AnonymousObjectTransformationInfo oldInfo = inliningContext.findAnonymousObjectTransformationInfo(owner);
if (oldInfo != null && isContinuation) {
info = oldInfo;
}
for (CapturedParamDesc capturedParamDesc : info.getAllRecapturedParameters()) {
visitFieldInsn(Opcodes.GETSTATIC, capturedParamDesc.getContainingLambdaName(), "$$$" + capturedParamDesc.getFieldName(), capturedParamDesc.getType().getDescriptor());
}
super.visitMethodInsn(opcode, info.getNewClassName(), name, info.getNewConstructorDescriptor(), itf);
//TODO: add new inner class also for other contexts
if (inliningContext.getParent() instanceof RegeneratedClassContext) {
inliningContext.getParent().typeRemapper.addAdditionalMappings(transformationInfo.getOldClassName(), transformationInfo.getNewClassName());
}
transformationInfo = null;
} else {
super.visitMethodInsn(opcode, owner, name, desc, itf);
}
} else if (!inliningContext.isInliningLambda && ReifiedTypeInliner.isNeedClassReificationMarker(new MethodInsnNode(opcode, owner, name, desc, false))) {
//we shouldn't process here content of inlining lambda it should be reified at external level
} else {
super.visitMethodInsn(opcode, owner, name, desc, itf);
}
}
@Override
public void visitFieldInsn(int opcode, @NotNull String owner, @NotNull String name, @NotNull String desc) {
if (opcode == Opcodes.GETSTATIC && (isAnonymousSingletonLoad(owner, name) || isWhenMappingAccess(owner, name))) {
handleAnonymousObjectRegeneration();
}
super.visitFieldInsn(opcode, owner, name, desc);
}
@Override
public void visitMaxs(int stack, int locals) {
lambdasFinallyBlocks = resultNode.tryCatchBlocks.size();
super.visitMaxs(stack, locals);
}
};
node.accept(lambdaInliner);
return resultNode;
}
use of org.jetbrains.org.objectweb.asm.commons.Method in project kotlin by JetBrains.
the class KotlinTypeMapper method mapDefaultMethod.
@NotNull
public Method mapDefaultMethod(@NotNull FunctionDescriptor functionDescriptor, @NotNull OwnerKind kind) {
Method jvmSignature = mapAsmMethod(functionDescriptor, kind);
Type ownerType = mapOwner(functionDescriptor);
boolean isConstructor = isConstructor(jvmSignature);
String descriptor = getDefaultDescriptor(jvmSignature, isStaticMethod(kind, functionDescriptor) || isConstructor ? null : ownerType.getDescriptor(), CodegenUtilKt.unwrapFrontendVersion(functionDescriptor));
return new Method(isConstructor ? "<init>" : jvmSignature.getName() + JvmAbi.DEFAULT_PARAMS_IMPL_SUFFIX, descriptor);
}
Aggregations