summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorschinz <schinz@epfl.ch>2004-03-05 15:12:45 +0000
committerschinz <schinz@epfl.ch>2004-03-05 15:12:45 +0000
commit00f558fd79569cd2fb8efd7c387f191811324e72 (patch)
treea1f032d2ef200c1cf9484d5571d275f841e27474
parent92d93e58ce68665aef715da23b2eafcbf7be1a46 (diff)
downloadscala-00f558fd79569cd2fb8efd7c387f191811324e72.tar.gz
scala-00f558fd79569cd2fb8efd7c387f191811324e72.tar.bz2
scala-00f558fd79569cd2fb8efd7c387f191811324e72.zip
- hack: turn private, constant fields into stat...
- hack: turn private, constant fields into static fields, to support serialization
-rw-r--r--sources/scalac/backend/jvm/GenJVM.java150
1 files changed, 105 insertions, 45 deletions
diff --git a/sources/scalac/backend/jvm/GenJVM.java b/sources/scalac/backend/jvm/GenJVM.java
index 1218164114..1f7e08754b 100644
--- a/sources/scalac/backend/jvm/GenJVM.java
+++ b/sources/scalac/backend/jvm/GenJVM.java
@@ -90,6 +90,9 @@ class GenJVM {
protected final Definitions defs;
protected final Primitives prims;
+ protected final Phase refCheckPhase;
+ protected final AddInterfacesPhase addInterfacesPhase;
+
protected final FJBGContext fjbgContext;
public GenJVM(Global global) {
@@ -97,6 +100,10 @@ class GenJVM {
this.defs = global.definitions;
this.prims = global.primitives;
+ this.refCheckPhase = global.PHASE.REFCHECK.phase();
+ this.addInterfacesPhase =
+ (AddInterfacesPhase)global.PHASE.ADDINTERFACES.phase();
+
this.fjbgContext = new FJBGContext();
initTypeMap();
@@ -142,6 +149,7 @@ class GenJVM {
Context ctx1 = enterClass(ctx, sym);
addValueClassMembers(ctx1, classDef);
+ addStaticClassMembers(ctx1, classDef);
if (ctx1.isModuleClass)
addModuleInstanceField(ctx1);
@@ -531,52 +539,9 @@ class GenJVM {
generatedType = JAVA_LANG_OBJECT_T;
break;
- case Literal(UNIT):
- maybeGenLoadUnit(ctx, expectedType);
- generatedType = expectedType;
- break;
- case Literal(BOOLEAN(boolean value)):
- ctx.code.emitPUSH(value);
- generatedType = JType.BOOLEAN;
- break;
- case Literal(BYTE(byte value)):
- ctx.code.emitPUSH(value);
- generatedType = JType.BYTE;
- break;
- case Literal(SHORT(short value)):
- ctx.code.emitPUSH(value);
- generatedType = JType.SHORT;
- break;
- case Literal(CHAR(char value)):
- ctx.code.emitPUSH(value);
- generatedType = JType.CHAR;
- break;
- case Literal(INT(int value)):
- ctx.code.emitPUSH(value);
- generatedType = JType.INT;
- break;
- case Literal(LONG(long value)):
- ctx.code.emitPUSH(value);
- generatedType = JType.LONG;
- break;
- case Literal(FLOAT(float value)):
- ctx.code.emitPUSH(value);
- generatedType = JType.FLOAT;
- break;
- case Literal(DOUBLE(double value)):
- ctx.code.emitPUSH(value);
- generatedType = JType.DOUBLE;
- break;
- case Literal(STRING(String value)):
- ctx.code.emitPUSH(value);
- generatedType = JAVA_LANG_STRING_T;
- break;
- case Literal(NULL):
- if (expectedType != JType.VOID) ctx.code.emitACONST_NULL();
- generatedType = expectedType;
- break;
case Literal(AConstant value):
- throw Debug.abort("unknown literal", value);
+ generatedType = genLoadLiteral(ctx, value, expectedType);
+ break;
case Empty:
case AbsTypeDef(_, _, _, _):
@@ -653,6 +618,46 @@ class GenJVM {
}
}
+ protected JType genLoadLiteral(Context ctx, AConstant lit, JType type) {
+ switch (lit) {
+ case UNIT:
+ maybeGenLoadUnit(ctx, type);
+ return type;
+ case BOOLEAN(boolean value):
+ ctx.code.emitPUSH(value);
+ return JType.BOOLEAN;
+ case BYTE(byte value):
+ ctx.code.emitPUSH(value);
+ return JType.BYTE;
+ case SHORT(short value):
+ ctx.code.emitPUSH(value);
+ return JType.SHORT;
+ case CHAR(char value):
+ ctx.code.emitPUSH(value);
+ return JType.CHAR;
+ case INT(int value):
+ ctx.code.emitPUSH(value);
+ return JType.INT;
+ case LONG(long value):
+ ctx.code.emitPUSH(value);
+ return JType.LONG;
+ case FLOAT(float value):
+ ctx.code.emitPUSH(value);
+ return JType.FLOAT;
+ case DOUBLE(double value):
+ ctx.code.emitPUSH(value);
+ return JType.DOUBLE;
+ case STRING(String value):
+ ctx.code.emitPUSH(value);
+ return JAVA_LANG_STRING_T;
+ case NULL:
+ if (type != JType.VOID) ctx.code.emitACONST_NULL();
+ return type;
+ default:
+ throw Debug.abort("unknown literal", lit);
+ }
+ }
+
/**
* Generate code to load the Unit value, iff the given type is an
* object type (i.e. something really has to be loaded on stack).
@@ -1473,6 +1478,8 @@ class GenJVM {
*/
protected JType typeStoJ(Type tp) {
switch (tp) {
+ case ConstantType(Type base, _):
+ return typeStoJ(base);
case TypeRef(_, Symbol sym, _):
Object value = typeMap.get(sym);
if (value != null) return (JType)value;
@@ -1721,6 +1728,59 @@ class GenJVM {
}
}
+ // The following function is a single big hack.
+ protected void addStaticClassMembers(Context ctx, Tree.ClassDef cDef) {
+ Symbol cSym = cDef.symbol();
+ HashMap/*<Symbol, AConstant>*/ staticMembers = new HashMap();
+ Symbol iSym = addInterfacesPhase.getInterfaceSymbol(cSym);
+ if (iSym != null) {
+ // Compute the list of static members to add.
+ Phase bkpCurrent = global.currentPhase;
+ global.currentPhase = refCheckPhase;
+ Scope.SymbolIterator memberIt =
+ new Scope.UnloadIterator(iSym.members().iterator());
+ while (memberIt.hasNext()) {
+ Symbol member = memberIt.next();
+ if (member.isTerm() && !member.isMethod() && member.isPrivate())
+ switch (member.info()) {
+ case ConstantType(_, AConstant value):
+ staticMembers.put(member, value);
+ }
+ }
+ global.currentPhase = bkpCurrent;
+
+ // Add them and initialize them.
+ JMethod classInitMeth =
+ ctx.clazz.addNewMethod(JAccessFlags.ACC_STATIC,
+ "<clinit>",
+ JType.VOID,
+ JType.EMPTY_ARRAY,
+ new String[0]);
+ Context ctx1 =
+ ctx.withMethod(classInitMeth, Collections.EMPTY_MAP, false);
+
+ Iterator smIt = staticMembers.keySet().iterator();
+ while (smIt.hasNext()) {
+ Symbol sm = (Symbol)smIt.next();
+ String smName = sm.name.toString();
+ JType tp = typeStoJ(sm.info());
+ JField field =
+ ctx1.clazz.addNewField((modifiersStoJ(sm.flags)
+ | JAccessFlags.ACC_STATIC
+ | JAccessFlags.ACC_PUBLIC)
+ & ~JAccessFlags.ACC_PRIVATE,
+ smName.substring(0,
+ smName.length()-1),
+ tp);
+ genLoadLiteral(ctx1, (AConstant)staticMembers.get(sm), tp);
+ ctx1.code.emitPUTSTATIC(ctx1.clazz.getName(),
+ field.getName(),
+ tp);
+ }
+ ctx1.code.emitRETURN();
+ }
+ }
+
/**
* Return true iff the given symbol is a static (in the Java
* sense) member of its owner.