Get rid of ConstructorFrameMap, drop CodegenContext#prepareFrame()

Also refactor FunctionGenerationStrategy to take FrameMap as an instance
instead of creating it in a subclass
This commit is contained in:
Alexander Udalov
2014-07-10 20:19:40 +04:00
parent 65c21561a4
commit 1949e24ffa
7 changed files with 55 additions and 133 deletions
@@ -1,48 +0,0 @@
/*
* Copyright 2010-2013 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jetbrains.jet.codegen;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.jet.lang.resolve.java.jvmSignature.JvmMethodParameterKind;
import org.jetbrains.jet.lang.resolve.java.jvmSignature.JvmMethodParameterSignature;
import org.jetbrains.jet.lang.resolve.java.jvmSignature.JvmMethodSignature;
import static org.jetbrains.jet.lang.resolve.java.AsmTypeConstants.OBJECT_TYPE;
public class ConstructorFrameMap extends FrameMap {
private int myOuterThisIndex = -1;
public ConstructorFrameMap(@NotNull JvmMethodSignature signature) {
enterTemp(OBJECT_TYPE); // this
for (JvmMethodParameterSignature parameterType : signature.getValueParameters()) {
if (parameterType.getKind() == JvmMethodParameterKind.OUTER) {
myOuterThisIndex = enterTemp(OBJECT_TYPE); // this0
}
else if (parameterType.getKind() != JvmMethodParameterKind.VALUE) {
enterTemp(parameterType.getAsmType());
}
else {
break;
}
}
}
public int getOuterThisIndex() {
return myOuterThisIndex;
}
}
@@ -297,8 +297,15 @@ public class FunctionCodegen extends ParentCodegenAware {
generateStaticDelegateMethodBody(mv, signature.getAsmMethod(), (PackageFacadeContext) context.getParentContext());
}
else {
FrameMap frameMap = strategy.getFrameMap(typeMapper, context);
FrameMap frameMap = new FrameMap();
if (context.getContextKind() == OwnerKind.IMPLEMENTATION) {
frameMap.enterTemp(OBJECT_TYPE); // 0 slot for this
}
for (JvmMethodParameterSignature parameter : signature.getValueParameters()) {
if (parameter.getKind() != JvmMethodParameterKind.VALUE) {
frameMap.enterTemp(parameter.getAsmType());
}
}
for (ValueParameterDescriptor parameter : functionDescriptor.getValueParameters()) {
frameMap.enter(parameter, typeMapper.mapType(parameter));
}
@@ -311,7 +318,7 @@ public class FunctionCodegen extends ParentCodegenAware {
genNotNullAssertionsForParameters(new InstructionAdapter(mv), parentCodegen.state, functionDescriptor, frameMap);
}
strategy.generateBody(mv, signature, context, parentCodegen);
strategy.generateBody(mv, frameMap, signature, context, parentCodegen);
}
Label methodEnd = new Label();
@@ -777,45 +784,45 @@ public class FunctionCodegen extends ParentCodegenAware {
final JvmMethodSignature jvmDelegateMethodSignature,
final JvmMethodSignature jvmOverriddenMethodSignature
) {
generateMethod(OtherOrigin(functionDescriptor),
jvmDelegateMethodSignature,
functionDescriptor,
new FunctionGenerationStrategy() {
@Override
public void generateBody(
@NotNull MethodVisitor mv,
@NotNull JvmMethodSignature signature,
@NotNull MethodContext context,
@NotNull MemberCodegen<?> parentCodegen
) {
Method overriddenMethod = jvmOverriddenMethodSignature.getAsmMethod();
Method delegateMethod = jvmDelegateMethodSignature.getAsmMethod();
generateMethod(
OtherOrigin(functionDescriptor), jvmDelegateMethodSignature, functionDescriptor,
new FunctionGenerationStrategy() {
@Override
public void generateBody(
@NotNull MethodVisitor mv,
@NotNull FrameMap frameMap,
@NotNull JvmMethodSignature signature,
@NotNull MethodContext context,
@NotNull MemberCodegen<?> parentCodegen
) {
Method overriddenMethod = jvmOverriddenMethodSignature.getAsmMethod();
Method delegateMethod = jvmDelegateMethodSignature.getAsmMethod();
Type[] argTypes = delegateMethod.getArgumentTypes();
Type[] originalArgTypes = overriddenMethod.getArgumentTypes();
Type[] argTypes = delegateMethod.getArgumentTypes();
Type[] originalArgTypes = overriddenMethod.getArgumentTypes();
InstructionAdapter iv = new InstructionAdapter(mv);
iv.load(0, OBJECT_TYPE);
field.put(field.type, iv);
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();
}
InstructionAdapter iv = new InstructionAdapter(mv);
iv.load(0, OBJECT_TYPE);
field.put(field.type, iv);
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();
}
String internalName = typeMapper.mapType(toClass).getInternalName();
if (toClass.getKind() == ClassKind.TRAIT) {
iv.invokeinterface(internalName, overriddenMethod.getName(), overriddenMethod.getDescriptor());
}
else {
iv.invokevirtual(internalName, overriddenMethod.getName(), overriddenMethod.getDescriptor());
}
String internalName = typeMapper.mapType(toClass).getInternalName();
if (toClass.getKind() == ClassKind.TRAIT) {
iv.invokeinterface(internalName, overriddenMethod.getName(), overriddenMethod.getDescriptor());
}
else {
iv.invokevirtual(internalName, overriddenMethod.getName(), overriddenMethod.getDescriptor());
}
StackValue.onStack(overriddenMethod.getReturnType()).put(delegateMethod.getReturnType(), iv);
StackValue.onStack(overriddenMethod.getReturnType()).put(delegateMethod.getReturnType(), iv);
iv.areturn(delegateMethod.getReturnType());
}
}
iv.areturn(delegateMethod.getReturnType());
}
}
);
}
}
@@ -19,36 +19,20 @@ package org.jetbrains.jet.codegen;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.jet.codegen.context.MethodContext;
import org.jetbrains.jet.codegen.state.GenerationState;
import org.jetbrains.jet.codegen.state.JetTypeMapper;
import org.jetbrains.jet.lang.descriptors.CallableDescriptor;
import org.jetbrains.jet.lang.psi.JetDeclarationWithBody;
import org.jetbrains.jet.lang.resolve.java.jvmSignature.JvmMethodSignature;
import org.jetbrains.org.objectweb.asm.MethodVisitor;
public abstract class FunctionGenerationStrategy {
private FrameMap frameMap;
public abstract void generateBody(
@NotNull MethodVisitor mv,
@NotNull FrameMap frameMap,
@NotNull JvmMethodSignature signature,
@NotNull MethodContext context,
@NotNull MemberCodegen<?> parentCodegen
);
@NotNull
protected FrameMap createFrameMap(@NotNull JetTypeMapper typeMapper, @NotNull MethodContext context) {
return context.prepareFrame(typeMapper);
}
@NotNull
public FrameMap getFrameMap(@NotNull JetTypeMapper typeMapper, @NotNull MethodContext context) {
if (frameMap == null) {
frameMap = createFrameMap(typeMapper, context);
}
return frameMap;
}
public static class FunctionDefault extends CodegenBased<CallableDescriptor> {
private final JetDeclarationWithBody declaration;
@@ -79,12 +63,12 @@ public abstract class FunctionGenerationStrategy {
@Override
public final void generateBody(
@NotNull MethodVisitor mv,
@NotNull FrameMap frameMap,
@NotNull JvmMethodSignature signature,
@NotNull MethodContext context,
@NotNull MemberCodegen<?> parentCodegen
) {
ExpressionCodegen codegen = new ExpressionCodegen(mv, getFrameMap(state.getTypeMapper(), context),
signature.getReturnType(), context, state, parentCodegen);
ExpressionCodegen codegen = new ExpressionCodegen(mv, frameMap, signature.getReturnType(), context, state, parentCodegen);
doGenerateBody(codegen, signature);
}
@@ -813,6 +813,7 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
@Override
public void generateBody(
@NotNull MethodVisitor mv,
@NotNull FrameMap frameMap,
@NotNull JvmMethodSignature signature,
@NotNull MethodContext context,
@NotNull MemberCodegen<?> parentCodegen
@@ -839,6 +840,7 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
@Override
public void generateBody(
@NotNull MethodVisitor mv,
@NotNull FrameMap frameMap,
@NotNull JvmMethodSignature signature,
@NotNull MethodContext context,
@NotNull MemberCodegen<?> parentCodegen
@@ -1151,16 +1153,10 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
lookupConstructorExpressionsInClosureIfPresent(constructorContext);
}
final JvmMethodSignature signature = typeMapper.mapSignature(constructorDescriptor);
JvmMethodSignature signature = typeMapper.mapSignature(constructorDescriptor);
functionCodegen.generateMethod(OtherOrigin(myClass, constructorDescriptor), signature, constructorDescriptor, constructorContext,
new FunctionGenerationStrategy.CodegenBased<ConstructorDescriptor>(state, constructorDescriptor) {
@NotNull
@Override
protected FrameMap createFrameMap(@NotNull JetTypeMapper typeMapper, @NotNull MethodContext context) {
return new ConstructorFrameMap(signature);
}
@Override
public void doGenerateBody(@NotNull ExpressionCodegen codegen, @NotNull JvmMethodSignature signature) {
generatePrimaryConstructorImpl(callableDescriptor, codegen, delegationFieldsInfo);
@@ -178,6 +178,7 @@ public class PackageCodegen {
@Override
public void generateBody(
@NotNull MethodVisitor mv,
@NotNull FrameMap frameMap,
@NotNull JvmMethodSignature signature,
@NotNull MethodContext context,
@NotNull MemberCodegen<?> parentCodegen
@@ -37,10 +37,10 @@ import org.jetbrains.org.objectweb.asm.commons.InstructionAdapter;
import java.util.Collections;
import java.util.List;
import static org.jetbrains.jet.lang.resolve.java.diagnostics.DiagnosticsPackage.OtherOrigin;
import static org.jetbrains.jet.lang.resolve.java.diagnostics.JvmDeclarationOrigin.NO_ORIGIN;
import static org.jetbrains.jet.codegen.binding.CodegenBinding.*;
import static org.jetbrains.jet.lang.resolve.java.AsmTypeConstants.OBJECT_TYPE;
import static org.jetbrains.jet.lang.resolve.java.diagnostics.DiagnosticsPackage.OtherOrigin;
import static org.jetbrains.jet.lang.resolve.java.diagnostics.JvmDeclarationOrigin.NO_ORIGIN;
import static org.jetbrains.org.objectweb.asm.Opcodes.*;
// SCRIPT: script code generator
@@ -146,7 +146,8 @@ public class ScriptCodegen extends MemberCodegen<JetScript> {
instructionAdapter.load(0, classType);
final FrameMap frameMap = methodContext.prepareFrame(typeMapper);
final FrameMap frameMap = new FrameMap();
frameMap.enterTemp(OBJECT_TYPE);
for (ScriptDescriptor importedScript : context.getEarlierScripts()) {
frameMap.enter(importedScript, OBJECT_TYPE);
@@ -40,7 +40,6 @@ import java.util.Map;
import static org.jetbrains.jet.codegen.AsmUtil.CAPTURED_THIS_FIELD;
import static org.jetbrains.jet.codegen.AsmUtil.getVisibilityAccessFlag;
import static org.jetbrains.jet.codegen.binding.CodegenBinding.*;
import static org.jetbrains.jet.lang.resolve.java.AsmTypeConstants.OBJECT_TYPE;
import static org.jetbrains.org.objectweb.asm.Opcodes.ACC_PRIVATE;
import static org.jetbrains.org.objectweb.asm.Opcodes.ACC_PROTECTED;
@@ -200,24 +199,6 @@ public abstract class CodegenContext<T extends DeclarationDescriptor> {
return new ClosureContext(typeMapper, funDescriptor, classDescriptor, this, localLookup);
}
@NotNull
public FrameMap prepareFrame(@NotNull JetTypeMapper typeMapper) {
FrameMap frameMap = new FrameMap();
if (getContextKind() != OwnerKind.PACKAGE) {
frameMap.enterTemp(OBJECT_TYPE); // 0 slot for this
}
CallableDescriptor receiverDescriptor = getCallableDescriptorWithReceiver();
if (receiverDescriptor != null) {
//noinspection ConstantConditions
Type type = typeMapper.mapType(receiverDescriptor.getReceiverParameter().getType());
frameMap.enterTemp(type); // Next slot for receiver
}
return frameMap;
}
@Nullable
public CodegenContext getParentContext() {
return parentContext;