diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/CodegenUtil.java b/compiler/backend/src/org/jetbrains/jet/codegen/CodegenUtil.java index 8bf312c2602..109166846cd 100644 --- a/compiler/backend/src/org/jetbrains/jet/codegen/CodegenUtil.java +++ b/compiler/backend/src/org/jetbrains/jet/codegen/CodegenUtil.java @@ -27,6 +27,8 @@ import org.jetbrains.jet.lang.types.lang.JetStandardClasses; import org.jetbrains.jet.lang.types.JetType; import java.util.Collections; +import java.util.Collection; +import java.util.Random; /** * @author abreslav @@ -36,6 +38,8 @@ public class CodegenUtil { private CodegenUtil() { } + private static final Random RANDOM = new Random(55L); + public static boolean isInterface(DeclarationDescriptor descriptor) { return descriptor instanceof ClassDescriptor && ((ClassDescriptor)descriptor).getKind() == ClassKind.TRAIT; } @@ -85,4 +89,16 @@ public class CodegenUtil { } return false; } + + public static String generateTmpVariableName(Collection existingNames) { + String prefix = "tmp"; + int i = RANDOM.nextInt(Integer.MAX_VALUE); + String name = prefix + i; + while (existingNames.contains(name)) { + i++; + name = prefix + i; + } + return name; + } + } diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/ExpressionCodegen.java b/compiler/backend/src/org/jetbrains/jet/codegen/ExpressionCodegen.java index 9890c1183de..2657a284950 100644 --- a/compiler/backend/src/org/jetbrains/jet/codegen/ExpressionCodegen.java +++ b/compiler/backend/src/org/jetbrains/jet/codegen/ExpressionCodegen.java @@ -75,6 +75,7 @@ public class ExpressionCodegen extends JetVisitor { private final CodegenContext context; private final Stack blockStackElements = new Stack(); + private final Collection localVariableNames = new HashSet(); static class BlockStackElement { } @@ -109,7 +110,14 @@ public class ExpressionCodegen extends JetVisitor { this.typeMapper = state.getInjector().getJetTypeMapper(); this.returnType = returnType; this.state = state; - this.v = new InstructionAdapter(v); + this.v = new InstructionAdapter(v) { + @Override + public void visitLocalVariable(String name, String desc, String signature, Label start, Label end, int index) { + super.visitLocalVariable(name, desc, signature, start, end, + index); + localVariableNames.add(name); + } + }; this.bindingContext = state.getBindingContext(); this.context = context; } @@ -138,6 +146,10 @@ public class ExpressionCodegen extends JetVisitor { return bindingContext; } + public Collection getLocalVariableNamesForExpression() { + return localVariableNames; + } + public void addTypeParameter(TypeParameterDescriptor typeParameter, StackValue expression) { typeParameterExpressions.put(typeParameter, expression); } diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/FunctionCodegen.java b/compiler/backend/src/org/jetbrains/jet/codegen/FunctionCodegen.java index 075d034e63a..198c87ffe52 100644 --- a/compiler/backend/src/org/jetbrains/jet/codegen/FunctionCodegen.java +++ b/compiler/backend/src/org/jetbrains/jet/codegen/FunctionCodegen.java @@ -30,6 +30,7 @@ import org.jetbrains.jet.lang.resolve.DescriptorUtils; import org.jetbrains.jet.lang.resolve.java.JvmAbi; import org.jetbrains.jet.lang.resolve.java.JvmClassName; import org.jetbrains.jet.lang.resolve.java.JvmStdlibNames; +import org.jetbrains.jet.lang.resolve.name.Name; import org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverDescriptor; import org.objectweb.asm.Label; import org.objectweb.asm.MethodVisitor; @@ -37,8 +38,7 @@ import org.objectweb.asm.Type; import org.objectweb.asm.commons.InstructionAdapter; import org.objectweb.asm.commons.Method; -import java.util.List; -import java.util.Set; +import java.util.*; import static org.objectweb.asm.Opcodes.*; @@ -203,6 +203,8 @@ public class FunctionCodegen { throw new IllegalStateException("mismatching kind in " + functionDescriptor); } + Map mapLabelsToDivideLocalVarVisibilityForSharedVar = new HashMap(); + if (kind instanceof OwnerKind.DelegateKind) { OwnerKind.DelegateKind dk = (OwnerKind.DelegateKind) kind; InstructionAdapter iv = new InstructionAdapter(mv); @@ -227,6 +229,11 @@ public class FunctionCodegen { mv.visitMethodInsn(INVOKESPECIAL, sharedVarType.getInternalName(), "", "()V"); mv.visitVarInsn(localVarType.getOpcode(ILOAD), index); mv.visitFieldInsn(PUTFIELD, sharedVarType.getInternalName(), "ref", StackValue.refType(localVarType).getDescriptor()); + + Label labelToDivideLocalVarForSharedVarVisibility = new Label(); + mv.visitLabel(labelToDivideLocalVarForSharedVarVisibility); + mapLabelsToDivideLocalVarVisibilityForSharedVar.put(parameter.getName(), labelToDivideLocalVarForSharedVarVisibility); + mv.visitVarInsn(sharedVarType.getOpcode(ISTORE), index); } } @@ -237,6 +244,12 @@ public class FunctionCodegen { Label methodEnd = new Label(); mv.visitLabel(methodEnd); + Collection localVariableNames = new HashSet(); + localVariableNames.addAll(codegen.getLocalVariableNamesForExpression()); + for (ValueParameterDescriptor parameterDescriptor : paramDescrs) { + localVariableNames.add(parameterDescriptor.getName().getName()); + } + int k = 0; if(expectedThisObject.exists()) { @@ -260,8 +273,22 @@ public class FunctionCodegen { for (ValueParameterDescriptor parameter : paramDescrs) { Type type = state.getInjector().getJetTypeMapper().mapType(parameter.getType(), MapTypeMode.VALUE); // TODO: specify signature - mv.visitLocalVariable(parameter.getName().getName(), type.getDescriptor(), null, methodBegin, methodEnd, k); - k += type.getSize(); + + Label divideLabel = mapLabelsToDivideLocalVarVisibilityForSharedVar.get(parameter.getName()); + String parameterName = parameter.getName().getName(); + if(divideLabel != null) { + Type sharedVarType = state.getInjector().getJetTypeMapper().getSharedVarType(parameter); + mv.visitLocalVariable(parameterName, type.getDescriptor(), null, methodBegin, divideLabel, k); + + String nameForSharedVar = CodegenUtil.generateTmpVariableName(localVariableNames); + localVariableNames.add(nameForSharedVar); + + mv.visitLocalVariable(nameForSharedVar, sharedVarType.getDescriptor(), null, divideLabel, methodEnd, k); + k += Math.max(type.getSize(), sharedVarType.getSize()); + } else { + mv.visitLocalVariable(parameter.getName().getName(), type.getDescriptor(), null, methodBegin, methodEnd, k); + k += type.getSize(); + } } endVisit(mv, null, fun);