Merge remote branch 'origin/master'

Conflicts:
	idea/tests/org/jetbrains/jet/resolve/JetResolveTest.java
This commit is contained in:
Andrey Breslav
2011-10-17 20:04:32 +04:00
31 changed files with 986 additions and 95 deletions
@@ -40,10 +40,10 @@ public abstract class ClassBodyCodegen {
public void generate() {
generateDeclaration();
generateSyntheticParts();
generateClassBody();
generateSyntheticParts();
generateStaticInitializer();
v.visitEnd();
@@ -4,8 +4,6 @@ import org.jetbrains.jet.lang.descriptors.ClassDescriptor;
import org.jetbrains.jet.lang.psi.*;
import org.jetbrains.jet.lang.resolve.BindingContext;
import org.objectweb.asm.ClassVisitor;
import org.objectweb.asm.Type;
import org.objectweb.asm.commons.InstructionAdapter;
/**
* @author max
@@ -25,7 +23,7 @@ public class ClassCodegen {
generateImplementation(parentContext, aClass, OwnerKind.IMPLEMENTATION);
final ClassContext contextForInners = parentContext.intoClass(descriptor, OwnerKind.IMPLEMENTATION);
final ClassContext contextForInners = parentContext.intoClass(null, descriptor, OwnerKind.IMPLEMENTATION);
for (JetDeclaration declaration : aClass.getDeclarations()) {
if (declaration instanceof JetClass && !(declaration instanceof JetEnumEntry)) {
generate(contextForInners, (JetClass) declaration);
@@ -36,11 +34,11 @@ public class ClassCodegen {
private void generateImplementation(ClassContext parentContext, JetClassOrObject aClass, OwnerKind kind) {
ClassDescriptor descriptor = state.getBindingContext().get(BindingContext.CLASS, aClass);
ClassVisitor v = state.forClassImplementation(descriptor);
new ImplementationBodyCodegen(aClass, parentContext.intoClass(descriptor, kind), v, state).generate();
new ImplementationBodyCodegen(aClass, parentContext.intoClass(null, descriptor, kind), v, state).generate();
if(aClass instanceof JetClass && ((JetClass)aClass).isTrait()) {
v = state.forTraitImplementation(descriptor);
new TraitImplBodyCodegen(aClass, parentContext.intoClass(descriptor, OwnerKind.TRAIT_IMPL), v, state).generate();
new TraitImplBodyCodegen(aClass, parentContext.intoClass(null, descriptor, OwnerKind.TRAIT_IMPL), v, state).generate();
}
}
@@ -1,6 +1,3 @@
/*
* @author max
*/
package org.jetbrains.jet.codegen;
import org.jetbrains.jet.lang.descriptors.ClassDescriptor;
@@ -14,18 +11,22 @@ import org.objectweb.asm.commons.InstructionAdapter;
import java.util.HashMap;
/*
* @author max
* @author alex.tkachman
*/
public class ClassContext {
public static final ClassContext STATIC = new ClassContext(null, OwnerKind.NAMESPACE, null, null, null);
private final DeclarationDescriptor contextType;
private final OwnerKind contextKind;
private final StackValue thisExpression;
private final ClassContext parentContext;
private final ClosureCodegen closure;
public final FunctionOrClosureCodegen closure;
private boolean thisWasUsed = false;
HashMap<JetType,Integer> typeInfoConstants;
public ClassContext(DeclarationDescriptor contextType, OwnerKind contextKind, StackValue thisExpression, ClassContext parentContext, ClosureCodegen closureCodegen) {
public ClassContext(DeclarationDescriptor contextType, OwnerKind contextKind, StackValue thisExpression, ClassContext parentContext, FunctionOrClosureCodegen closureCodegen) {
this.contextType = contextType;
this.contextKind = contextKind;
this.thisExpression = thisExpression;
@@ -60,11 +61,11 @@ public class ClassContext {
return new ClassContext(descriptor, OwnerKind.NAMESPACE, null, this, null);
}
public ClassContext intoClass(ClassDescriptor descriptor, OwnerKind kind) {
public ClassContext intoClass(FunctionOrClosureCodegen closure, ClassDescriptor descriptor, OwnerKind kind) {
final StackValue thisValue;
thisValue = StackValue.local(0, JetTypeMapper.TYPE_OBJECT);
return new ClassContext(descriptor, kind, thisValue, this, null);
return new ClassContext(descriptor, kind, thisValue, this, closure);
}
public ClassContext intoFunction(FunctionDescriptor descriptor) {
@@ -140,13 +141,21 @@ public class ClassContext {
}
public StackValue lookupInContext(DeclarationDescriptor d, InstructionAdapter v) {
final ClosureCodegen top = closure;
final FunctionOrClosureCodegen top = closure;
if (top != null) {
final StackValue answer = top.lookupInContext(d);
if (answer != null) return answer;
final StackValue thisContext = getThisExpression();
thisContext.put(thisContext.type, v);
if(thisContext instanceof StackValue.Local) {
}
else if(thisContext instanceof StackValue.InstanceField) {
StackValue.InstanceField instanceField = (StackValue.InstanceField) thisContext;
v.getfield(instanceField.owner, instanceField.name, instanceField.type.getDescriptor());
}
else {
throw new UnsupportedOperationException();
}
}
return parentContext != null ? parentContext.lookupInContext(d, v) : null;
@@ -26,19 +26,10 @@ import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
public class ClosureCodegen {
public final GenerationState state;
private final ExpressionCodegen exprContext;
private final ClassContext context;
private ClassVisitor cv = null;
public String name = null;
private Map<DeclarationDescriptor, EnclosedValueDescriptor> closure = new LinkedHashMap<DeclarationDescriptor, EnclosedValueDescriptor>();
public class ClosureCodegen extends FunctionOrClosureCodegen {
public ClosureCodegen(GenerationState state, ExpressionCodegen exprContext, ClassContext context) {
this.state = state;
this.exprContext = exprContext;
this.context = context;
super(exprContext, context, state);
}
public static Method erasedInvokeSignature(FunctionDescriptor fd) {
@@ -57,31 +48,6 @@ public class ClosureCodegen {
return state.getTypeMapper().mapSignature("invoke", fd);
}
public StackValue lookupInContext(DeclarationDescriptor d) {
if (d instanceof VariableDescriptor) {
VariableDescriptor vd = (VariableDescriptor) d;
EnclosedValueDescriptor answer = closure.get(vd);
if (answer != null) return answer.getInnerValue();
final int idx = exprContext.lookupLocal(vd);
if (idx < 0) return null;
final Type type = state.getTypeMapper().mapType(vd.getOutType());
StackValue outerValue = StackValue.local(idx, type);
final String fieldName = "$" + (closure.size() + 1);
StackValue innerValue = StackValue.field(type, name, fieldName, false);
cv.visitField(Opcodes.ACC_PUBLIC, fieldName, type.getDescriptor(), null, null);
answer = new EnclosedValueDescriptor(d, innerValue, outerValue);
closure.put(d, answer);
return innerValue;
}
return null;
}
public GeneratedAnonymousClassDescriptor gen(JetFunctionLiteralExpression fun) {
final Pair<String, ClassVisitor> nameAndVisitor = state.forAnonymousSubclass(fun);
@@ -120,7 +86,7 @@ public class ClosureCodegen {
final Method constructor = generateConstructor(funClass, captureThis, funDescriptor.getReturnType());
if (captureThis) {
cv.visitField(Opcodes.ACC_PRIVATE, "this$0", enclosingType.getDescriptor(), null, null);
cv.visitField(0, "this$0", enclosingType.getDescriptor(), null, null);
}
cv.visitEnd();
@@ -192,7 +158,9 @@ public class ClosureCodegen {
}
for (DeclarationDescriptor descriptor : closure.keySet()) {
argTypes[i++] = state.getTypeMapper().mapType(((VariableDescriptor) descriptor).getOutType());
final Type sharedVarType = exprContext.getSharedVarType(descriptor);
final Type type = sharedVarType != null ? sharedVarType : state.getTypeMapper().mapType(((VariableDescriptor) descriptor).getOutType());
argTypes[i++] = type;
}
final Method constructor = new Method("<init>", Type.VOID_TYPE, argTypes);
@@ -551,7 +551,7 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
final Method cons = closure.getConstructor();
if (closure.isCaptureThis()) {
thisToStack();
v.load(0, JetTypeMapper.TYPE_OBJECT);
}
for (int i = 0; i < closure.getArgs().size(); i++) {
@@ -566,16 +566,43 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
@Override
public StackValue visitObjectLiteralExpression(JetObjectLiteralExpression expression, StackValue receiver) {
GeneratedAnonymousClassDescriptor descriptor = state.generateObjectLiteral(expression, this, context);
Type type = Type.getObjectType(descriptor.getClassname());
FunctionOrClosureCodegen closureCodegen = new FunctionOrClosureCodegen(this, context, state);
GeneratedAnonymousClassDescriptor closure = state.generateObjectLiteral(expression, closureCodegen);
Type type = Type.getObjectType(closure.getClassname());
v.anew(type);
v.dup();
v.load(0, JetTypeMapper.TYPE_OBJECT);
String jvmDescriptor = descriptor.getConstructor().getDescriptor().replace("(","(" + typeMapper.jetImplementationType((ClassDescriptor) contextType()));
v.invokespecial(descriptor.getClassname(), "<init>", jvmDescriptor);
return StackValue.onStack(type);
final List<Type> consArgTypes = new LinkedList<Type>(Arrays.asList(closure.getConstructor().getArgumentTypes()));
if (consArgTypes.size() > 0) {
v.load(0, JetTypeMapper.TYPE_OBJECT);
}
for (DeclarationDescriptor descriptor : closureCodegen.closure.keySet()) {
final Type sharedVarType = getSharedVarType(descriptor);
consArgTypes.add(sharedVarType != null ? sharedVarType : state.getTypeMapper().mapType(((VariableDescriptor) descriptor).getOutType()));
final EnclosedValueDescriptor valueDescriptor = closureCodegen.closure.get(descriptor);
valueDescriptor.getOuterValue().put(sharedVarType, v);
}
Method cons = new Method("<init>", Type.VOID_TYPE, consArgTypes.toArray(new Type[consArgTypes.size()]));
v.invokespecial(closure.getClassname(), "<init>", cons.getDescriptor());
return StackValue.onStack(Type.getObjectType(closure.getClassname()));
}
Type getSharedVarType(DeclarationDescriptor variableDescriptor) {
if(!(variableDescriptor instanceof VariableDescriptor))
return null;
Boolean aBoolean = bindingContext.get(BindingContext.MUST_BE_WRAPPED_IN_A_REF, (VariableDescriptor) variableDescriptor);
if (aBoolean != null && aBoolean) {
JetType outType = ((VariableDescriptor) variableDescriptor).getOutType();
return StackValue.sharedTypeForType(typeMapper.mapType(outType));
}
else {
return null;
}
}
private StackValue generateBlock(List<JetElement> statements) {
Label blockStart = new Label();
v.mark(blockStart);
@@ -584,7 +611,9 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
if (statement instanceof JetProperty) {
final VariableDescriptor variableDescriptor = bindingContext.get(BindingContext.VARIABLE, statement);
assert variableDescriptor != null;
final Type type = typeMapper.mapType(variableDescriptor.getOutType());
final Type sharedVarType = getSharedVarType(variableDescriptor);
final Type type = sharedVarType != null ? sharedVarType : typeMapper.mapType(variableDescriptor.getOutType());
myMap.enter(variableDescriptor, type.getSize());
}
}
@@ -608,10 +637,17 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
JetProperty var = (JetProperty) statement;
VariableDescriptor variableDescriptor = bindingContext.get(BindingContext.VARIABLE, var);
assert variableDescriptor != null;
Type outType = typeMapper.mapType(variableDescriptor.getOutType());
int index = myMap.leave(variableDescriptor);
v.visitLocalVariable(var.getName(), outType.getDescriptor(), null, blockStart, blockEnd, index);
final Type sharedVarType = getSharedVarType(variableDescriptor);
final Type type = sharedVarType != null ? sharedVarType : typeMapper.mapType(variableDescriptor.getOutType());
if(sharedVarType != null) {
v.aconst(null);
v.store(index, JetTypeMapper.TYPE_OBJECT);
}
v.visitLocalVariable(var.getName(), type.getDescriptor(), null, blockStart, blockEnd, index);
}
}
@@ -699,8 +735,14 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
else {
int index = lookupLocal(descriptor);
if (index >= 0) {
Type sharedVarType = getSharedVarType(descriptor);
final JetType outType = ((VariableDescriptor) descriptor).getOutType();
return StackValue.local(index, typeMapper.mapType(outType));
if(sharedVarType != null) {
return StackValue.shared(index, typeMapper.mapType(outType));
}
else {
return StackValue.local(index, typeMapper.mapType(outType));
}
}
else if (descriptor instanceof PropertyDescriptor) {
final PropertyDescriptor propertyDescriptor = (PropertyDescriptor) descriptor;
@@ -785,6 +827,12 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
if (value == null) {
throw new UnsupportedOperationException("don't know how to generate reference " + descriptor);
}
if(value instanceof StackValue.FieldForSharedVar) {
StackValue.FieldForSharedVar fieldForSharedVar = (StackValue.FieldForSharedVar) value;
Type sharedType = StackValue.sharedTypeForType(value.type);
v.visitFieldInsn(Opcodes.GETFIELD, fieldForSharedVar.owner, fieldForSharedVar.name, sharedType.getDescriptor());
}
return value;
}
}
@@ -1617,12 +1665,27 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
assert index >= 0;
final Type sharedVarType = getSharedVarType(variableDescriptor);
assert variableDescriptor != null;
Type varType = typeMapper.mapType(variableDescriptor.getOutType());
if(sharedVarType != null) {
v.anew(sharedVarType);
v.dup();
v.invokespecial(sharedVarType.getInternalName(), "<init>", "()V");
v.store(index, JetTypeMapper.TYPE_OBJECT);
}
JetExpression initializer = property.getInitializer();
if (initializer != null) {
assert variableDescriptor != null;
Type type = typeMapper.mapType(variableDescriptor.getOutType());
gen(initializer, type);
v.store(index, type);
if(sharedVarType == null) {
gen(initializer, varType);
v.store(index, varType);
}
else {
v.load(index, JetTypeMapper.TYPE_OBJECT);
gen(initializer, varType);
v.putfield(sharedVarType.getInternalName(), "ref", sharedVarType == JetTypeMapper.TYPE_SHARED_VAR ? "Ljava/lang/Object;" : varType.getDescriptor());
}
}
return StackValue.none();
}
@@ -3,6 +3,7 @@ package org.jetbrains.jet.codegen;
import gnu.trove.TObjectIntHashMap;
import gnu.trove.TObjectIntIterator;
import org.jetbrains.jet.lang.descriptors.DeclarationDescriptor;
import org.jetbrains.jet.lang.resolve.BindingContext;
import java.util.ArrayList;
import java.util.List;
@@ -98,6 +98,23 @@ public class FunctionCodegen {
iv.areturn(jvmSignature.getReturnType());
}
else {
for (int i = 0; i < paramDescrs.size(); i++) {
ValueParameterDescriptor parameter = paramDescrs.get(i);
Type sharedVarType = codegen.getSharedVarType(parameter);
Type localVarType = state.getTypeMapper().mapType(parameter.getOutType());
if(sharedVarType != null) {
int index = frameMap.getIndex(parameter);
mv.visitTypeInsn(Opcodes.NEW, sharedVarType.getInternalName());
mv.visitInsn(Opcodes.DUP);
mv.visitInsn(Opcodes.DUP);
mv.visitMethodInsn(Opcodes.INVOKESPECIAL, sharedVarType.getInternalName(), "<init>", "()V");
mv.visitVarInsn(localVarType.getOpcode(Opcodes.ILOAD), index);
mv.visitFieldInsn(Opcodes.PUTFIELD, sharedVarType.getInternalName(), "ref", StackValue.refType(localVarType).getDescriptor());
mv.visitVarInsn(sharedVarType.getOpcode(Opcodes.ISTORE), index);
}
}
codegen.returnExpression(bodyExpressions);
}
mv.visitMaxs(0, 0);
@@ -0,0 +1,57 @@
package org.jetbrains.jet.codegen;
import org.jetbrains.jet.lang.descriptors.DeclarationDescriptor;
import org.jetbrains.jet.lang.descriptors.VariableDescriptor;
import org.objectweb.asm.ClassVisitor;
import org.objectweb.asm.Opcodes;
import org.objectweb.asm.Type;
import java.util.LinkedHashMap;
import java.util.Map;
/**
* @author alex.tkachman
*/
public class FunctionOrClosureCodegen {
public final GenerationState state;
protected final ExpressionCodegen exprContext;
protected final ClassContext context;
protected ClassVisitor cv = null;
public String name = null;
protected Map<DeclarationDescriptor, EnclosedValueDescriptor> closure = new LinkedHashMap<DeclarationDescriptor, EnclosedValueDescriptor>();
public FunctionOrClosureCodegen(ExpressionCodegen exprContext, ClassContext context, GenerationState state) {
this.exprContext = exprContext;
this.context = context;
this.state = state;
}
public StackValue lookupInContext(DeclarationDescriptor d) {
if (d instanceof VariableDescriptor) {
VariableDescriptor vd = (VariableDescriptor) d;
EnclosedValueDescriptor answer = closure.get(vd);
if (answer != null) return answer.getInnerValue();
final int idx = exprContext.lookupLocal(vd);
if (idx < 0) return null;
final Type sharedVarType = exprContext.getSharedVarType(vd);
Type localType = state.getTypeMapper().mapType(vd.getOutType());
final Type type = sharedVarType != null ? sharedVarType : localType;
StackValue outerValue = StackValue.local(idx, type);
final String fieldName = "$" + (closure.size() + 1); // + "$" + vd.getName();
StackValue innerValue = sharedVarType != null ? StackValue.fieldForSharedVar(localType, name, fieldName) : StackValue.field(type, name, fieldName, false);
cv.visitField(Opcodes.ACC_PUBLIC, fieldName, type.getDescriptor(), null, null);
answer = new EnclosedValueDescriptor(d, innerValue, outerValue);
closure.put(d, answer);
return innerValue;
}
return null;
}
}
@@ -9,6 +9,7 @@ import com.intellij.util.containers.Stack;
import org.jetbrains.jet.codegen.intrinsics.IntrinsicMethods;
import org.jetbrains.jet.lang.cfg.pseudocode.JetControlFlowDataTraceFactory;
import org.jetbrains.jet.lang.descriptors.ClassDescriptor;
import org.jetbrains.jet.lang.descriptors.ConstructorDescriptor;
import org.jetbrains.jet.lang.psi.*;
import org.jetbrains.jet.lang.resolve.AnalyzingUtils;
import org.jetbrains.jet.lang.resolve.BindingContext;
@@ -120,13 +121,19 @@ public class GenerationState {
}
}
public GeneratedAnonymousClassDescriptor generateObjectLiteral(JetObjectLiteralExpression literal, ExpressionCodegen context, ClassContext classContext) {
Pair<String, ClassVisitor> nameAndVisitor = forAnonymousSubclass(literal.getObjectDeclaration());
public GeneratedAnonymousClassDescriptor generateObjectLiteral(JetObjectLiteralExpression literal, FunctionOrClosureCodegen closure) {
JetObjectDeclaration objectDeclaration = literal.getObjectDeclaration();
Pair<String, ClassVisitor> nameAndVisitor = forAnonymousSubclass(objectDeclaration);
final ClassContext objectContext = classContext.intoClass(getBindingContext().get(BindingContext.CLASS, literal.getObjectDeclaration()), OwnerKind.IMPLEMENTATION);
closure.cv = nameAndVisitor.getSecond();
closure.name = nameAndVisitor.getFirst();
final ClassContext objectContext = closure.context.intoClass(closure, getBindingContext().get(BindingContext.CLASS, objectDeclaration), OwnerKind.IMPLEMENTATION);
new ImplementationBodyCodegen(literal.getObjectDeclaration(), objectContext, nameAndVisitor.getSecond(), this).generate();
return new GeneratedAnonymousClassDescriptor(nameAndVisitor.first, new Method("<init>", "()V"), false);
new ImplementationBodyCodegen(objectDeclaration, objectContext, nameAndVisitor.getSecond(), this).generate();
ConstructorDescriptor constructorDescriptor = closure.state.getBindingContext().get(BindingContext.CONSTRUCTOR, objectDeclaration);
CallableMethod callableMethod = closure.state.getTypeMapper().mapToCallableMethod(constructorDescriptor, OwnerKind.IMPLEMENTATION);
return new GeneratedAnonymousClassDescriptor(nameAndVisitor.first, callableMethod.getSignature(), false);
}
public static void prepareAnonymousClasses(JetElement aClass, final JetTypeMapper typeMapper) {
@@ -225,6 +225,22 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
callableMethod = state.getTypeMapper().mapToCallableMethod(constructorDescriptor, kind);
method = callableMethod.getSignature();
}
int firstClosureIndex = -1;
if(context.closure != null) {
final List<Type> consArgTypes = new LinkedList<Type>(Arrays.asList(method.getArgumentTypes()));
firstClosureIndex = consArgTypes.size()+1;
Map<DeclarationDescriptor, EnclosedValueDescriptor> closure = context.closure.closure;
for (DeclarationDescriptor descriptor : closure.keySet()) {
final Type sharedVarType = context.closure.exprContext.getSharedVarType(descriptor);
consArgTypes.add(sharedVarType != null ? sharedVarType : state.getTypeMapper().mapType(((VariableDescriptor) descriptor).getOutType()));
}
method = new Method("<init>", Type.VOID_TYPE, consArgTypes.toArray(new Type[consArgTypes.size()]));
}
int flags = Opcodes.ACC_PUBLIC; // TODO
final MethodVisitor mv = v.visitMethod(flags, "<init>", method.getDescriptor(), null, null);
mv.visitCode();
@@ -300,7 +316,7 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
iv.putfield(classname, delegateField, fieldDesc);
JetClass superClass = (JetClass) state.getBindingContext().get(BindingContext.DESCRIPTOR_TO_DECLARATION, superClassDescriptor);
final ClassContext delegateContext = context.intoClass(superClassDescriptor,
final ClassContext delegateContext = context.intoClass(null, superClassDescriptor,
new OwnerKind.DelegateKind(StackValue.field(fieldType, classname, delegateField, false),
JetTypeMapper.jvmNameForInterface(superClassDescriptor)));
generateDelegates(superClass, delegateContext, overridden);
@@ -322,6 +338,17 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
generateTypeInfoInitializer(frameMap.getFirstTypeParameter(), frameMap.getTypeParameterCount(), iv);
}
if(context.closure != null) {
Map<DeclarationDescriptor, EnclosedValueDescriptor> closure = context.closure.closure;
int k = 0;
for (DeclarationDescriptor varDescr : closure.keySet()) {
final Type sharedVarType = context.closure.exprContext.getSharedVarType(varDescr);
iv.load(0, JetTypeMapper.TYPE_OBJECT);
iv.load(firstClosureIndex + k, StackValue.refType(sharedVarType));
iv.putfield(state.getTypeMapper().jvmName(descriptor, OwnerKind.IMPLEMENTATION), "$" + (k+1), sharedVarType.getDescriptor());
}
}
generateInitializers(codegen, iv);
generateTraitMethods(codegen);
@@ -59,6 +59,15 @@ public class JetTypeMapper {
public static final Type TYPE_FUNCTION1 = Type.getObjectType("jet/Function1");
public static final Type TYPE_ITERATOR = Type.getObjectType("jet/Iterator");
public static final Type TYPE_INT_RANGE = Type.getObjectType("jet/IntRange");
public static final Type TYPE_SHARED_VAR = Type.getObjectType("jet/refs/SharedVar$Object");
public static final Type TYPE_SHARED_INT = Type.getObjectType("jet/refs/SharedVar$Int");
public static final Type TYPE_SHARED_DOUBLE = Type.getObjectType("jet/refs/SharedVar$Double");
public static final Type TYPE_SHARED_FLOAT = Type.getObjectType("jet/refs/SharedVar$Float");
public static final Type TYPE_SHARED_BYTE = Type.getObjectType("jet/refs/SharedVar$Byte");
public static final Type TYPE_SHARED_SHORT = Type.getObjectType("jet/refs/SharedVar$Short");
public static final Type TYPE_SHARED_CHAR = Type.getObjectType("jet/refs/SharedVar$Char");
public static final Type TYPE_SHARED_LONG = Type.getObjectType("jet/refs/SharedVar$Long");
public static final Type TYPE_SHARED_BOOLEAN = Type.getObjectType("jet/refs/SharedVar$Boolean");
public JetTypeMapper(JetStandardLibrary standardLibrary, BindingContext bindingContext) {
this.standardLibrary = standardLibrary;
@@ -11,6 +11,7 @@ import org.objectweb.asm.commons.Method;
/**
* @author yole
* @author alex.tkachman
*/
public abstract class StackValue {
public final Type type;
@@ -59,6 +60,10 @@ public abstract class StackValue {
return new Local(index, type);
}
public static StackValue shared(int index, Type type) {
return new Shared(index, type);
}
public static StackValue onStack(Type type) {
return type == Type.VOID_TYPE ? none() : new OnStack(type);
}
@@ -225,7 +230,11 @@ public abstract class StackValue {
public static StackValue none() {
return None.INSTANCE;
}
public static StackValue fieldForSharedVar(Type type, String name, String fieldName) {
return new FieldForSharedVar(type, name, fieldName);
}
private static class None extends StackValue {
public static None INSTANCE = new None();
private None() {
@@ -496,9 +505,9 @@ public abstract class StackValue {
}
private static class Field extends StackValue {
private final String owner;
private final String name;
static class Field extends StackValue {
final String owner;
final String name;
private final boolean isStatic;
public Field(Type type, String owner, String name, boolean isStatic) {
@@ -531,9 +540,9 @@ public abstract class StackValue {
}
}
private static class InstanceField extends StackValue {
private final String owner;
private final String name;
static class InstanceField extends StackValue {
final String owner;
final String name;
public InstanceField(Type type, String owner, String name) {
super(type);
@@ -625,4 +634,106 @@ public abstract class StackValue {
generator.gen(expression, type);
}
}
public static class Shared extends StackValue {
private final int index;
public Shared(int index, Type type) {
super(type);
this.index = index;
}
@Override
public void put(Type type, InstructionAdapter v) {
v.load(index, JetTypeMapper.TYPE_OBJECT);
Type refType = refType(this.type);
Type sharedType = sharedTypeForType(this.type);
v.visitFieldInsn(Opcodes.GETFIELD, sharedType.getInternalName(), "ref", refType.getDescriptor());
StackValue.onStack(refType).coerce(this.type, v);
StackValue.onStack(this.type).coerce(type, v);
}
@Override
public void store(InstructionAdapter v) {
v.load(index, JetTypeMapper.TYPE_OBJECT);
v.swap();
Type refType = refType(this.type);
Type sharedType = sharedTypeForType(this.type);
v.visitFieldInsn(Opcodes.PUTFIELD, sharedType.getInternalName(), "ref", refType.getDescriptor());
}
}
public static Type sharedTypeForType(Type type) {
switch(type.getSort()) {
case Type.OBJECT:
case Type.ARRAY:
return JetTypeMapper.TYPE_SHARED_VAR;
case Type.BYTE:
return JetTypeMapper.TYPE_SHARED_BYTE;
case Type.SHORT:
return JetTypeMapper.TYPE_SHARED_SHORT;
case Type.CHAR:
return JetTypeMapper.TYPE_SHARED_CHAR;
case Type.INT:
return JetTypeMapper.TYPE_SHARED_INT;
case Type.BOOLEAN:
return JetTypeMapper.TYPE_SHARED_BOOLEAN;
case Type.FLOAT:
return JetTypeMapper.TYPE_SHARED_FLOAT;
case Type.DOUBLE:
return JetTypeMapper.TYPE_SHARED_DOUBLE;
default:
throw new UnsupportedOperationException();
}
}
public static Type refType(Type type) {
if(type.getSort() == Type.OBJECT || type.getSort() == Type.ARRAY)
return JetTypeMapper.TYPE_OBJECT;
return type;
}
static class FieldForSharedVar extends StackValue {
final String owner;
final String name;
public FieldForSharedVar(Type type, String owner, String name) {
super(type);
this.owner = owner;
this.name = name;
}
@Override
public void dupReceiver(InstructionAdapter v, int below) {
if (below == 1) {
v.dupX1();
}
else {
v.dup();
}
}
@Override
public void put(Type type, InstructionAdapter v) {
Type sharedType = sharedTypeForType(this.type);
Type refType = refType(this.type);
v.visitFieldInsn(Opcodes.GETFIELD, sharedType.getInternalName(), "ref", refType.getDescriptor());
StackValue.onStack(refType).coerce(this.type, v);
StackValue.onStack(this.type).coerce(type, v);
}
@Override
public void store(InstructionAdapter v) {
v.visitFieldInsn(Opcodes.PUTFIELD, sharedTypeForType(type).getInternalName(), "ref", refType(type).getDescriptor());
}
}
}