Local variable shouldn't be visible in debugger before initialization

This commit is contained in:
Natalia Ukhorskaya
2015-01-13 16:42:09 +03:00
parent 89f8442705
commit f5aefc96fb
8 changed files with 128 additions and 49 deletions
@@ -1539,20 +1539,7 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> implem
}
}
if (statement instanceof JetMultiDeclaration) {
JetMultiDeclaration multiDeclaration = (JetMultiDeclaration) statement;
for (JetMultiDeclarationEntry entry : multiDeclaration.getEntries()) {
generateLocalVariableDeclaration(entry, blockEnd, leaveTasks);
}
}
if (statement instanceof JetVariableDeclaration) {
generateLocalVariableDeclaration((JetVariableDeclaration) statement, blockEnd, leaveTasks);
}
if (statement instanceof JetNamedFunction) {
generateLocalFunctionDeclaration((JetNamedFunction) statement, leaveTasks);
}
putDescriptorIntoFrameMap(statement);
boolean isExpression = !iterator.hasNext() && !isStatement;
if (isExpression && labelBeforeLastExpression != null) {
@@ -1567,6 +1554,8 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> implem
else {
result.put(Type.VOID_TYPE, v);
}
removeDescriptorFromFrameMap(statement, blockEnd, leaveTasks);
}
return new StackValueWithLeaveTask(answer, new ExtensionFunction0<StackValueWithLeaveTask, Unit>() {
@@ -1583,34 +1572,97 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> implem
});
}
private void generateLocalVariableDeclaration(
@NotNull JetVariableDeclaration variableDeclaration,
final @NotNull Label blockEnd,
@NotNull
private Type getVariableType(@NotNull VariableDescriptor variableDescriptor) {
Type sharedVarType = typeMapper.getSharedVarType(variableDescriptor);
return sharedVarType != null ? sharedVarType : asmType(variableDescriptor.getType());
}
private static boolean isSharedVarType(@NotNull Type type) {
return type.getSort() == Type.OBJECT && type.getInternalName().startsWith(REF_TYPE_PREFIX);
}
private void putDescriptorIntoFrameMap(@NotNull JetElement statement) {
if (statement instanceof JetMultiDeclaration) {
JetMultiDeclaration multiDeclaration = (JetMultiDeclaration) statement;
for (JetMultiDeclarationEntry entry : multiDeclaration.getEntries()) {
putLocalVariableIntoFrameMap(entry);
}
}
if (statement instanceof JetVariableDeclaration) {
putLocalVariableIntoFrameMap((JetVariableDeclaration) statement);
}
if (statement instanceof JetNamedFunction) {
DeclarationDescriptor descriptor = bindingContext.get(DECLARATION_TO_DESCRIPTOR, statement);
myFrameMap.enter(descriptor, OBJECT_TYPE);
}
}
private void putLocalVariableIntoFrameMap(@NotNull JetVariableDeclaration statement) {
VariableDescriptor variableDescriptor = bindingContext.get(VARIABLE, statement);
assert variableDescriptor != null;
Type type = getVariableType(variableDescriptor);
int index = myFrameMap.enter(variableDescriptor, type);
if (isSharedVarType(type)) {
v.anew(type);
v.dup();
v.invokespecial(type.getInternalName(), "<init>", "()V", false);
v.store(index, OBJECT_TYPE);
}
}
private void removeDescriptorFromFrameMap(
@NotNull JetElement statement,
@NotNull Label blockEnd,
@NotNull List<Function<StackValue, Void>> leaveTasks
) {
final VariableDescriptor variableDescriptor = bindingContext.get(VARIABLE, variableDeclaration);
if (statement instanceof JetMultiDeclaration) {
JetMultiDeclaration multiDeclaration = (JetMultiDeclaration) statement;
for (JetMultiDeclarationEntry entry : multiDeclaration.getEntries()) {
removeLocalVariableFromFrameMap(entry, blockEnd, leaveTasks);
}
}
if (statement instanceof JetVariableDeclaration) {
removeLocalVariableFromFrameMap((JetVariableDeclaration) statement, blockEnd, leaveTasks);
}
if (statement instanceof JetNamedFunction) {
final DeclarationDescriptor descriptor = bindingContext.get(DECLARATION_TO_DESCRIPTOR, statement);
leaveTasks.add(new Function<StackValue, Void>() {
@Override
public Void fun(StackValue value) {
myFrameMap.leave(descriptor);
return null;
}
});
}
}
private void removeLocalVariableFromFrameMap(
@NotNull JetVariableDeclaration statement,
final Label blockEnd,
@NotNull List<Function<StackValue, Void>> leaveTasks
) {
final VariableDescriptor variableDescriptor = bindingContext.get(VARIABLE, statement);
assert variableDescriptor != null;
final Type type = getVariableType(variableDescriptor);
final Label scopeStart = new Label();
v.mark(scopeStart);
final Type sharedVarType = typeMapper.getSharedVarType(variableDescriptor);
final Type type = sharedVarType != null ? sharedVarType : asmType(variableDescriptor.getType());
int index = myFrameMap.enter(variableDescriptor, type);
if (sharedVarType != null) {
v.anew(sharedVarType);
v.dup();
v.invokespecial(sharedVarType.getInternalName(), "<init>", "()V", false);
v.store(index, OBJECT_TYPE);
}
leaveTasks.add(new Function<StackValue, Void>() {
@Override
public Void fun(StackValue answer) {
int index = myFrameMap.leave(variableDescriptor);
if (sharedVarType != null) {
if (isSharedVarType(type)) {
v.aconst(null);
v.store(index, OBJECT_TYPE);
}
@@ -1620,22 +1672,6 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> implem
});
}
private void generateLocalFunctionDeclaration(
@NotNull JetNamedFunction namedFunction,
@NotNull List<Function<StackValue, Void>> leaveTasks
) {
final DeclarationDescriptor descriptor = bindingContext.get(DECLARATION_TO_DESCRIPTOR, namedFunction);
myFrameMap.enter(descriptor, OBJECT_TYPE);
leaveTasks.add(new Function<StackValue, Void>() {
@Override
public Void fun(StackValue value) {
myFrameMap.leave(descriptor);
return null;
}
});
}
public boolean isShouldMarkLineNumbers() {
return shouldMarkLineNumbers;
}
@@ -1235,7 +1235,7 @@ public abstract class StackValue {
if (primitiveType == null) throw new UnsupportedOperationException();
String typeName = primitiveType.getTypeName().getIdentifier();
return Type.getObjectType("kotlin/jvm/internal/Ref$" + typeName + "Ref");
return Type.getObjectType(REF_TYPE_PREFIX + typeName + "Ref");
}
}
@@ -154,6 +154,14 @@ public class RedundantBoxingMethodTransformer extends MethodTransformer {
int from = insnList.indexOf(localVariableNode.start) + 1;
int to = insnList.indexOf(localVariableNode.end) - 1;
Frame<BasicValue> frameForFromInstr = frames[from];
if (frameForFromInstr != null) {
BasicValue localVarValue = frameForFromInstr.getLocal(localVariableNode.index);
if (localVarValue != null) {
values.add(localVarValue);
}
}
for (int i = from; i <= to; i++) {
if (i < 0 || i >= insnList.size()) continue;