# HG changeset patch # User Jaroslav Tulach # Date 1453697601 -3600 # Node ID 9cdc403018b5938ea30c4a2c4eebb226d330a0e5 # Parent 34efbdde4eca54a55fa766c85ec45b624e736481 Resolving field access during compilation time diff -r 34efbdde4eca -r 9cdc403018b5 rt/vm/src/main/java/org/apidesign/vm4brwsr/ByteCodeToJavaScript.java --- a/rt/vm/src/main/java/org/apidesign/vm4brwsr/ByteCodeToJavaScript.java Mon Jan 25 05:14:25 2016 +0100 +++ b/rt/vm/src/main/java/org/apidesign/vm4brwsr/ByteCodeToJavaScript.java Mon Jan 25 05:53:21 2016 +0100 @@ -103,7 +103,11 @@ return "(refs_" + classOperation + " || (refs_" + classOperation + " = " + accessClass(classOperation) + "(false)))"; } - protected String accessField(String object, String[] fieldInfoName) + protected FieldData findField(String[] fieldInfoName) throws IOException { + return null; + } + + protected String accessField(String object, FieldData data, String[] fieldInfoName) throws IOException { String mangledName = "_" + fieldInfoName[1]; return object + "." + mangledName; @@ -1419,12 +1423,21 @@ int indx = readUShortArg(byteCodes, i); String[] fi = jc.getFieldInfoName(indx); final int type = VarType.fromFieldType(fi[2].charAt(0)); - final String mangleClass = mangleClassName(fi[0]); - final String mangleClassAccess = accessClassFalse(mangleClass); - smapper.replace(this, type, "@2.call(@1)", - smapper.getA(0), - accessField(mangleClassAccess, fi) - ); + FieldData field = findField(fi); + if (field == null) { + final String mangleClass = mangleClassName(fi[0]); + final String mangleClassAccess = accessClassFalse(mangleClass); + smapper.replace(this, type, "@2.call(@1)", + smapper.getA(0), + accessField(mangleClassAccess, null, fi) + ); + } else { + final String fieldOwner = mangleClassName(field.cls.getClassName()); + smapper.replace(this, type, "@1.@2", + smapper.getA(0), + accessField(fieldOwner, field, fi) + ); + } i += 2; addReference(fi[0]); break; @@ -1433,12 +1446,23 @@ int indx = readUShortArg(byteCodes, i); String[] fi = jc.getFieldInfoName(indx); final int type = VarType.fromFieldType(fi[2].charAt(0)); - final String mangleClass = mangleClassName(fi[0]); - final String mangleClassAccess = accessClassFalse(mangleClass); - emit(smapper, this, "@3.call(@2, @1);", - smapper.popT(type), - smapper.popA(), - accessField(mangleClassAccess, fi)); + FieldData field = findField(fi); + if (field == null) { + final String mangleClass = mangleClassName(fi[0]); + final String mangleClassAccess = accessClassFalse(mangleClass); + emit(smapper, this, "@3.call(@2, @1);", + smapper.popT(type), + smapper.popA(), + accessField(mangleClassAccess, null, fi) + ); + } else { + final String fieldOwner = mangleClassName(field.cls.getClassName()); + emit(smapper, this, "@2.@3 = @1;", + smapper.popT(type), + smapper.popA(), + accessField(fieldOwner, field, fi) + ); + } i += 2; addReference(fi[0]); break; @@ -1448,7 +1472,7 @@ String[] fi = jc.getFieldInfoName(indx); final int type = VarType.fromFieldType(fi[2].charAt(0)); String ac = accessClassFalse(mangleClassName(fi[0])); - String af = accessField(ac, fi); + String af = accessField(ac, null, fi); smapper.assign(this, type, af + "()"); i += 2; addReference(fi[0]); diff -r 34efbdde4eca -r 9cdc403018b5 rt/vm/src/main/java/org/apidesign/vm4brwsr/VM.java --- a/rt/vm/src/main/java/org/apidesign/vm4brwsr/VM.java Mon Jan 25 05:14:25 2016 +0100 +++ b/rt/vm/src/main/java/org/apidesign/vm4brwsr/VM.java Mon Jan 25 05:53:21 2016 +0100 @@ -310,15 +310,22 @@ } @Override - protected String accessField(String object, String[] fieldInfoName) + protected FieldData findField(String[] fieldInfoName) throws IOException { + FieldData field = classDataCache.findField( + fieldInfoName[0], fieldInfoName[1], fieldInfoName[2] + ); + return field != null && canAccessDirectly(field.cls) ? field : null; + } + + @Override + protected String accessField(String object, FieldData field, String[] fieldInfoName) throws IOException { - final FieldData field = - classDataCache.findField(fieldInfoName[0], - fieldInfoName[1], - fieldInfoName[2]); - String mangledName = "_" + fieldInfoName[1]; - return accessNonVirtualMember(object, mangledName, - (field != null) ? field.cls : null); + if (field != null) { + return "fld_" + object + "_" + field.getName(); + } else { + String mangledName = "_" + fieldInfoName[1]; + return accessNonVirtualMember(object, mangledName, null); + } } @Override @@ -403,11 +410,9 @@ return (exportedMethodFinder.getFound() != null); } - private String accessNonVirtualMember(String object, - String mangledName, - ClassData declaringClass) { + private boolean canAccessDirectly(ClassData declaringClass) { if (declaringClass == null) { - return object + "['" + mangledName + "']"; + return false; } final String className = declaringClass.getClassName(); if ( @@ -415,9 +420,17 @@ "java/lang/reflect/Array".equals(className) || isExternalClass(className) ) { - return object + "['" + mangledName + "']"; + return false; } - return object + "." + mangledName; + return true; + } + + private String accessNonVirtualMember( + String object, String mangledName, ClassData declaringClass + ) { + return canAccessDirectly(declaringClass) ? + object + "." + mangledName : + object + "['" + mangledName + "']"; } private final class ExportedMethodFinder