Overridable class member access type closure
authorLubomir Nerad <lubomir.nerad@oracle.com>
Mon, 06 May 2013 18:06:08 +0200
branchclosure
changeset 1084f5c9934a252c
parent 1083 9d6130cb464f
child 1085 6a4ef883e233
Overridable class member access type
rt/vm/src/main/java/org/apidesign/vm4brwsr/ByteCodeToJavaScript.java
rt/vm/src/main/java/org/apidesign/vm4brwsr/ClassDataCache.java
rt/vm/src/main/java/org/apidesign/vm4brwsr/VM.java
     1.1 --- a/rt/vm/src/main/java/org/apidesign/vm4brwsr/ByteCodeToJavaScript.java	Mon May 06 11:57:29 2013 +0200
     1.2 +++ b/rt/vm/src/main/java/org/apidesign/vm4brwsr/ByteCodeToJavaScript.java	Mon May 06 18:06:08 2013 +0200
     1.3 @@ -59,6 +59,11 @@
     1.4          return classOperation;
     1.5      }
     1.6  
     1.7 +    protected String accessMember(String object, String mangledName,
     1.8 +                                  String[] fieldInfoName) throws IOException {
     1.9 +        return object + "." + mangledName;
    1.10 +    }
    1.11 +
    1.12      protected void declaredClass(ClassData classData, String mangledName)
    1.13              throws IOException {
    1.14      }
    1.15 @@ -94,7 +99,11 @@
    1.16       */
    1.17      
    1.18      public String compile(InputStream classFile) throws IOException {
    1.19 -        this.jc = new ClassData(classFile);
    1.20 +        return compile(new ClassData(classFile));
    1.21 +    }
    1.22 +
    1.23 +    protected String compile(ClassData classData) throws IOException {
    1.24 +        this.jc = classData;
    1.25          if (jc.getMajor_version() < 50) {
    1.26              throw new IOException("Can't compile " + jc.getClassName() + ". Class file version " + jc.getMajor_version() + "."
    1.27                  + jc.getMinor_version() + " - recompile with -target 1.6 (at least)."
    1.28 @@ -1195,10 +1204,11 @@
    1.29                      final int type = VarType.fromFieldType(fi[2].charAt(0));
    1.30                      final String mangleClass = mangleSig(fi[0]);
    1.31                      final String mangleClassAccess = accessClass(mangleClass);
    1.32 -                    emit(out, "var @2 = @4(false)._@3.call(@1);",
    1.33 +                    emit(out, "var @2 = @3.call(@1);",
    1.34                           smapper.popA(),
    1.35 -                         smapper.pushT(type), fi[1], mangleClassAccess
    1.36 -                    );
    1.37 +                         smapper.pushT(type),
    1.38 +                         accessMember(mangleClassAccess + "(false)",
    1.39 +                                      "_" + fi[1], fi));
    1.40                      i += 2;
    1.41                      break;
    1.42                  }
    1.43 @@ -1208,11 +1218,11 @@
    1.44                      final int type = VarType.fromFieldType(fi[2].charAt(0));
    1.45                      final String mangleClass = mangleSig(fi[0]);
    1.46                      final String mangleClassAccess = accessClass(mangleClass);
    1.47 -                    emit(out, "@4(false)._@3.call(@2, @1);",
    1.48 +                    emit(out, "@3.call(@2, @1);",
    1.49                           smapper.popT(type),
    1.50 -                         smapper.popA(), fi[1], 
    1.51 -                         mangleClassAccess
    1.52 -                    );
    1.53 +                         smapper.popA(),
    1.54 +                         accessMember(mangleClassAccess + "(false)",
    1.55 +                                      "_" + fi[1], fi));
    1.56                      i += 2;
    1.57                      break;
    1.58                  }
    1.59 @@ -1220,9 +1230,11 @@
    1.60                      int indx = readUShortArg(byteCodes, i);
    1.61                      String[] fi = jc.getFieldInfoName(indx);
    1.62                      final int type = VarType.fromFieldType(fi[2].charAt(0));
    1.63 -                    emit(out, "var @1 = @2(false)._@3();",
    1.64 +                    emit(out, "var @1 = @2();",
    1.65                           smapper.pushT(type),
    1.66 -                         accessClass(fi[0].replace('/', '_')), fi[1]);
    1.67 +                         accessMember(accessClass(fi[0].replace('/', '_'))
    1.68 +                                          + "(false)",
    1.69 +                                      "_" + fi[1], fi));
    1.70                      i += 2;
    1.71                      addReference(fi[0]);
    1.72                      break;
    1.73 @@ -1231,8 +1243,10 @@
    1.74                      int indx = readUShortArg(byteCodes, i);
    1.75                      String[] fi = jc.getFieldInfoName(indx);
    1.76                      final int type = VarType.fromFieldType(fi[2].charAt(0));
    1.77 -                    emit(out, "@1(false)._@2(@3);",
    1.78 -                         accessClass(fi[0].replace('/', '_')), fi[1],
    1.79 +                    emit(out, "@1(@2);",
    1.80 +                         accessMember(accessClass(fi[0].replace('/', '_'))
    1.81 +                                          + "(false)",
    1.82 +                                      "_" + fi[1], fi),
    1.83                           smapper.popT(type));
    1.84                      i += 2;
    1.85                      addReference(fi[0]);
    1.86 @@ -1478,12 +1492,12 @@
    1.87          }
    1.88  
    1.89          final String in = mi[0];
    1.90 -        out.append(accessClass(in.replace('/', '_')));
    1.91 -        out.append("(false).");
    1.92 -        if (mn.startsWith("cons_")) {
    1.93 -            out.append("constructor.");
    1.94 -        }
    1.95 -        out.append(mn);
    1.96 +        out.append(accessMember(
    1.97 +                       accessClass(in.replace('/', '_')) + "(false)",
    1.98 +                       mn.startsWith("cons_")
    1.99 +                              ? "constructor." + mn
   1.100 +                              : mn,
   1.101 +                       mi));
   1.102          if (isStatic) {
   1.103              out.append('(');
   1.104          } else {
   1.105 @@ -1522,8 +1536,7 @@
   1.106                 .append(" = ");
   1.107          }
   1.108  
   1.109 -        out.append(vars[0]).append('.');
   1.110 -        out.append(mn);
   1.111 +        out.append(accessMember(vars[0].toString(), mn, mi));
   1.112          out.append('(');
   1.113          String sep = "";
   1.114          for (int j = 1; j < numArguments; ++j) {
     2.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     2.2 +++ b/rt/vm/src/main/java/org/apidesign/vm4brwsr/ClassDataCache.java	Mon May 06 18:06:08 2013 +0200
     2.3 @@ -0,0 +1,55 @@
     2.4 +/**
     2.5 + * Back 2 Browser Bytecode Translator
     2.6 + * Copyright (C) 2012 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
     2.7 + *
     2.8 + * This program is free software: you can redistribute it and/or modify
     2.9 + * it under the terms of the GNU General Public License as published by
    2.10 + * the Free Software Foundation, version 2 of the License.
    2.11 + *
    2.12 + * This program is distributed in the hope that it will be useful,
    2.13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
    2.14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    2.15 + * GNU General Public License for more details.
    2.16 + *
    2.17 + * You should have received a copy of the GNU General Public License
    2.18 + * along with this program. Look for COPYING file in the top folder.
    2.19 + * If not, see http://opensource.org/licenses/GPL-2.0.
    2.20 + */
    2.21 +package org.apidesign.vm4brwsr;
    2.22 +
    2.23 +import java.io.IOException;
    2.24 +import java.io.InputStream;
    2.25 +import java.util.HashMap;
    2.26 +import java.util.Map;
    2.27 +import org.apidesign.bck2brwsr.core.ExtraJavaScript;
    2.28 +import org.apidesign.vm4brwsr.ByteCodeParser.ClassData;
    2.29 +
    2.30 +@ExtraJavaScript(processByteCode = false, resource="")
    2.31 +final class ClassDataCache {
    2.32 +    private static final Object MISSING_CLASS = new Object();
    2.33 +
    2.34 +    private final Bck2Brwsr.Resources resources;
    2.35 +    private final Map<String, Object> classDataMap;
    2.36 +
    2.37 +    ClassDataCache(final Bck2Brwsr.Resources resources) {
    2.38 +        this.resources = resources;
    2.39 +
    2.40 +        classDataMap = new HashMap<String, Object>();
    2.41 +    }
    2.42 +
    2.43 +    ClassData getClassData(final String className) throws IOException {
    2.44 +        Object cacheEntry = classDataMap.get(className);
    2.45 +        if (cacheEntry == null) {
    2.46 +            final InputStream is = loadClass(resources, className);
    2.47 +            cacheEntry = (is != null) ? new ClassData(is) : MISSING_CLASS;
    2.48 +            classDataMap.put(className, cacheEntry);
    2.49 +        }
    2.50 +
    2.51 +        return (cacheEntry != MISSING_CLASS) ? (ClassData) cacheEntry : null;
    2.52 +    }
    2.53 +
    2.54 +    private static InputStream loadClass(Bck2Brwsr.Resources l, String name)
    2.55 +            throws IOException {
    2.56 +        return l.get(name + ".class"); // NOI18N
    2.57 +    }
    2.58 +}
     3.1 --- a/rt/vm/src/main/java/org/apidesign/vm4brwsr/VM.java	Mon May 06 11:57:29 2013 +0200
     3.2 +++ b/rt/vm/src/main/java/org/apidesign/vm4brwsr/VM.java	Mon May 06 18:06:08 2013 +0200
     3.3 @@ -28,12 +28,15 @@
     3.4   * @author Jaroslav Tulach <jtulach@netbeans.org>
     3.5   */
     3.6  abstract class VM extends ByteCodeToJavaScript {
     3.7 -    protected final Bck2Brwsr.Resources resources;
     3.8 +    protected final ClassDataCache classDataCache;
     3.9 +
    3.10 +    private final Bck2Brwsr.Resources resources;
    3.11      private final ExportedSymbols exportedSymbols;
    3.12  
    3.13      private VM(Appendable out, Bck2Brwsr.Resources resources) {
    3.14          super(out);
    3.15          this.resources = resources;
    3.16 +        this.classDataCache = new ClassDataCache(resources);
    3.17          this.exportedSymbols = new ExportedSymbols(resources);
    3.18      }
    3.19  
    3.20 @@ -231,10 +234,6 @@
    3.21          }
    3.22      }
    3.23  
    3.24 -    private static InputStream loadClass(Bck2Brwsr.Resources l, String name) throws IOException {
    3.25 -        return l.get(name + ".class"); // NOI18N
    3.26 -    }
    3.27 -
    3.28      static String toString(String name) throws IOException {
    3.29          StringBuilder sb = new StringBuilder();
    3.30  //        compile(sb, name);
    3.31 @@ -268,6 +267,19 @@
    3.32          return "vm." + className;
    3.33      }
    3.34  
    3.35 +    @Override
    3.36 +    protected String accessMember(String object, String mangledName,
    3.37 +                                  String[] fieldInfoName) throws IOException {
    3.38 +        final ClassData declaringClass =
    3.39 +                classDataCache.getClassData(fieldInfoName[0]);
    3.40 +        if (declaringClass == null) {
    3.41 +            return object + "['" + mangledName + "']";
    3.42 +        }
    3.43 +
    3.44 +        // TODO
    3.45 +        return object + "." + mangledName;
    3.46 +    }
    3.47 +
    3.48      private static final class Standalone extends VM {
    3.49          private Standalone(Appendable out, Bck2Brwsr.Resources resources) {
    3.50              super(out, resources);
    3.51 @@ -322,11 +334,11 @@
    3.52  
    3.53          @Override
    3.54          protected String generateClass(String className) throws IOException {
    3.55 -            InputStream is = loadClass(resources, className);
    3.56 -            if (is == null) {
    3.57 +            ClassData classData = classDataCache.getClassData(className);
    3.58 +            if (classData == null) {
    3.59                  throw new IOException("Can't find class " + className);
    3.60              }
    3.61 -            return compile(is);
    3.62 +            return compile(classData);
    3.63          }
    3.64  
    3.65          @Override
    3.66 @@ -362,8 +374,8 @@
    3.67  
    3.68          @Override
    3.69          protected String generateClass(String className) throws IOException {
    3.70 -            InputStream is = loadClass(resources, className);
    3.71 -            if (is == null) {
    3.72 +            ClassData classData = classDataCache.getClassData(className);
    3.73 +            if (classData == null) {
    3.74                  out.append("\n").append(assignClass(
    3.75                                              className.replace('/', '_')))
    3.76                     .append("function() {\n  return link('")
    3.77 @@ -374,7 +386,7 @@
    3.78                  return null;
    3.79              }
    3.80  
    3.81 -            return compile(is);
    3.82 +            return compile(classData);
    3.83          }
    3.84  
    3.85          @Override