rt/vm/src/main/java/org/apidesign/vm4brwsr/VM.java
branchclosure
changeset 1513 ba912ef24b27
parent 1508 e995e8d39240
parent 1509 16f50abb439b
child 1514 d2401e2648af
     1.1 --- a/rt/vm/src/main/java/org/apidesign/vm4brwsr/VM.java	Tue Apr 29 15:25:58 2014 +0200
     1.2 +++ b/rt/vm/src/main/java/org/apidesign/vm4brwsr/VM.java	Wed Apr 30 15:04:10 2014 +0200
     1.3 @@ -85,11 +85,11 @@
     1.4  
     1.5      private void doCompile(StringArray names, StringArray asBinary) throws IOException {
     1.6          generatePrologue();
     1.7 -        out.append(
     1.8 +        append(
     1.9                  "\n  var invoker = {};");
    1.10          generateBody(names);
    1.11          for (String invokerMethod: invokerMethods.toArray()) {
    1.12 -            out.append("\n  invoker." + invokerMethod + " = function(target) {"
    1.13 +            append("\n  invoker." + invokerMethod + " = function(target) {"
    1.14                  + "\n    return function() {"
    1.15                  + "\n      return target['" + invokerMethod + "'].apply(target, arguments);"
    1.16                  + "\n    };"
    1.17 @@ -98,19 +98,19 @@
    1.18          }
    1.19          
    1.20          for (String r : asBinary.toArray()) {
    1.21 -            out.append("\n  ").append(getExportsObject()).append(".registerResource('");
    1.22 -            out.append(r).append("', '");
    1.23 +            append("\n  ").append(getExportsObject()).append(".registerResource('");
    1.24 +            append(r).append("', '");
    1.25              InputStream is = this.resources.get(r);
    1.26              byte[] arr = new byte[is.available()];
    1.27              int len = is.read(arr);
    1.28              if (len != arr.length) {
    1.29                  throw new IOException("Not read as much as expected for " + r + " expected: " + arr.length + " was: " + len);
    1.30              }
    1.31 -            out.append(btoa(arr));
    1.32 -            out.append("');");
    1.33 +            append(btoa(arr));
    1.34 +            append("');");
    1.35          }
    1.36          
    1.37 -        out.append("\n");
    1.38 +        append("\n");
    1.39          generateEpilogue();
    1.40      }
    1.41  
    1.42 @@ -131,7 +131,7 @@
    1.43      protected final void declaredClass(ClassData classData, String mangledName)
    1.44              throws IOException {
    1.45          if (exportedSymbols.isExported(classData)) {
    1.46 -            out.append("\n").append(getExportsObject()).append("['")
    1.47 +            append("\n").append(getExportsObject()).append("['")
    1.48                                                 .append(mangledName)
    1.49                                                 .append("'] = ")
    1.50                              .append(accessClass(mangledName))
    1.51 @@ -167,7 +167,7 @@
    1.52  
    1.53      private void exportMember(String destObject, String memberName)
    1.54              throws IOException {
    1.55 -        out.append("\n").append(destObject).append("['")
    1.56 +        append("\n").append(destObject).append("['")
    1.57                                             .append(memberName)
    1.58                                             .append("'] = ")
    1.59                          .append(destObject).append(".").append(memberName)
    1.60 @@ -177,11 +177,15 @@
    1.61      private void generateBody(StringArray names) throws IOException {
    1.62          StringArray processed = new StringArray();
    1.63          StringArray initCode = new StringArray();
    1.64 +        StringArray skipClass = new StringArray();
    1.65          for (String baseClass : names.toArray()) {
    1.66              references.add(baseClass);
    1.67              for (;;) {
    1.68                  String name = null;
    1.69                  for (String n : references.toArray()) {
    1.70 +                    if (skipClass.contains(n)) {
    1.71 +                        continue;
    1.72 +                    }
    1.73                      if (processed.contains(n)) {
    1.74                          continue;
    1.75                      }
    1.76 @@ -190,28 +194,18 @@
    1.77                  if (name == null) {
    1.78                      break;
    1.79                  }
    1.80 -
    1.81 +                InputStream is = resources.get(name + ".class");
    1.82 +                if (is == null) {
    1.83 +                    lazyReference(this, name);
    1.84 +                    skipClass.add(name);
    1.85 +                    continue;
    1.86 +                }
    1.87                  try {
    1.88                      String ic = generateClass(name);
    1.89                      processed.add(name);
    1.90                      initCode.add(ic == null ? "" : ic);
    1.91                  } catch (RuntimeException ex) {
    1.92 -                    if (out instanceof CharSequence) {
    1.93 -                        CharSequence seq = (CharSequence)out;
    1.94 -                        int lastBlock = seq.length();
    1.95 -                        while (lastBlock-- > 0) {
    1.96 -                            if (seq.charAt(lastBlock) == '{') {
    1.97 -                                break;
    1.98 -                            }
    1.99 -                        }
   1.100 -                        throw new IOException("Error while compiling " + name + "\n"
   1.101 -                            + seq.subSequence(lastBlock + 1, seq.length()), ex
   1.102 -                        );
   1.103 -                    } else {
   1.104 -                        throw new IOException("Error while compiling " + name + "\n"
   1.105 -                            + out, ex
   1.106 -                        );
   1.107 -                    }
   1.108 +                    throw new IOException("Error while compiling " + name + "\n", ex);
   1.109                  }
   1.110              }
   1.111  
   1.112 @@ -223,7 +217,7 @@
   1.113                  if (emul == null) {
   1.114                      throw new IOException("Can't find " + resource);
   1.115                  }
   1.116 -                readResource(emul, out);
   1.117 +                readResource(emul, this);
   1.118              }
   1.119              scripts = new StringArray();
   1.120  
   1.121 @@ -235,12 +229,53 @@
   1.122                  if (indx >= 0) {
   1.123                      final String theCode = initCode.toArray()[indx];
   1.124                      if (!theCode.isEmpty()) {
   1.125 -                        out.append(theCode).append("\n");
   1.126 +                        append(theCode).append("\n");
   1.127                      }
   1.128                      initCode.toArray()[indx] = "";
   1.129                  }
   1.130              }
   1.131          }
   1.132 +/*
   1.133 +        append(
   1.134 +              "  return vm;\n"
   1.135 +            + "  };\n"
   1.136 +            + "  function mangleClass(name) {\n"
   1.137 +            + "    return name.replace__Ljava_lang_String_2Ljava_lang_CharSequence_2Ljava_lang_CharSequence_2(\n"
   1.138 +            + "      '_', '_1').replace__Ljava_lang_String_2CC('.','_');\n"
   1.139 +            + "  };\n"
   1.140 +            + "  global.bck2brwsr = function() {\n"
   1.141 +            + "    var args = Array.prototype.slice.apply(arguments);\n"
   1.142 +            + "    var vm = fillInVMSkeleton({});\n"
   1.143 +            + "    var loader = {};\n"
   1.144 +            + "    loader.vm = vm;\n"
   1.145 +            + "    loader.loadClass = function(name) {\n"
   1.146 +            + "      var attr = mangleClass(name);\n"
   1.147 +            + "      var fn = vm[attr];\n"
   1.148 +            + "      if (fn) return fn(false);\n"
   1.149 +            + "      return vm.org_apidesign_vm4brwsr_VMLazy(false).\n"
   1.150 +            + "        load__Ljava_lang_Object_2Ljava_lang_Object_2Ljava_lang_String_2_3Ljava_lang_Object_2(loader, name, args);\n"
   1.151 +            + "    }\n"
   1.152 +            + "    if (vm.loadClass) {\n"
   1.153 +            + "      throw 'Cannot initialize the bck2brwsr VM twice!';\n"
   1.154 +            + "    }\n"
   1.155 +            + "    vm.loadClass = loader.loadClass;\n"
   1.156 +            + "    vm._reload = function(name, byteCode) {;\n"
   1.157 +            + "      var attr = mangleClass(name);\n"
   1.158 +            + "      delete vm[attr];\n"
   1.159 +            + "      return vm.org_apidesign_vm4brwsr_VMLazy(false).\n"
   1.160 +            + "        reload__Ljava_lang_Object_2Ljava_lang_Object_2Ljava_lang_String_2_3Ljava_lang_Object_2_3B(loader, name, args, byteCode);\n"
   1.161 +            + "    };\n"
   1.162 +            + "    vm.loadBytes = function(name, skip) {\n"
   1.163 +            + "      return vm.org_apidesign_vm4brwsr_VMLazy(false).\n"
   1.164 +            + "        loadBytes___3BLjava_lang_Object_2Ljava_lang_String_2_3Ljava_lang_Object_2I(loader, name, args, typeof skip == 'number' ? skip : 0);\n"
   1.165 +            + "    }\n"
   1.166 +            + "    vm.java_lang_reflect_Array(false);\n"
   1.167 +            + "    vm.org_apidesign_vm4brwsr_VMLazy(false).\n"
   1.168 +            + "      loadBytes___3BLjava_lang_Object_2Ljava_lang_String_2_3Ljava_lang_Object_2I(loader, null, args, 0);\n"
   1.169 +            + "    return loader;\n"
   1.170 +            + "  };\n");
   1.171 +        append("}(this));");
   1.172 +*/
   1.173      }
   1.174  
   1.175      private static void readResource(InputStream emul, Appendable out) throws IOException {
   1.176 @@ -442,12 +477,12 @@
   1.177  
   1.178          @Override
   1.179          protected void generatePrologue() throws IOException {
   1.180 -            out.append("(function VM(global) {var fillInVMSkeleton = function(vm) {");
   1.181 +            append("(function VM(global) {var fillInVMSkeleton = function(vm) {");
   1.182          }
   1.183  
   1.184          @Override
   1.185          protected void generateEpilogue() throws IOException {
   1.186 -            out.append(
   1.187 +            append(
   1.188                    "  return vm;\n"
   1.189                  + "  };\n"
   1.190                  + "  var extensions = [];\n"
   1.191 @@ -495,22 +530,22 @@
   1.192                  + "      throw 'Cannot initialize the bck2brwsr VM twice!';\n"
   1.193                  + "    }\n"
   1.194                  + "    vm.loadClass = loader.loadClass;\n"
   1.195 -                + "    vm.loadBytes = function(name) {\n"
   1.196 +                + "    vm.loadBytes = function(name, skip) {\n"
   1.197                  + "      if (resources[name]) return resources[name][0];\n"
   1.198                  + "      return vm.org_apidesign_vm4brwsr_VMLazy(false).\n"
   1.199 -                + "        loadBytes___3BLjava_lang_Object_2Ljava_lang_String_2_3Ljava_lang_Object_2(loader, name, args);\n"
   1.200 +                + "        loadBytes___3BLjava_lang_Object_2Ljava_lang_String_2_3Ljava_lang_Object_2I(loader, name, args, typeof skip == 'number' ? skip : 0);\n"
   1.201                  + "    }\n"
   1.202                  + "    vm.java_lang_reflect_Array(false);\n"
   1.203                  + "    vm.org_apidesign_vm4brwsr_VMLazy(false).\n"
   1.204 -                + "      loadBytes___3BLjava_lang_Object_2Ljava_lang_String_2_3Ljava_lang_Object_2(loader, null, args);\n"
   1.205 +                + "      loadBytes___3BLjava_lang_Object_2Ljava_lang_String_2_3Ljava_lang_Object_2I(loader, null, args, 0);\n"
   1.206                  + "    return loader;\n"
   1.207                  + "  };\n");
   1.208 -            out.append(
   1.209 +            append(
   1.210                    "  global.bck2brwsr.registerExtension = function(extension) {\n"
   1.211                  + "    extensions.push(extension);\n"
   1.212                  + "    return null;\n"
   1.213                  + "  };\n");
   1.214 -            out.append("}(this));");
   1.215 +            append("}(this));");
   1.216          }
   1.217  
   1.218          @Override
   1.219 @@ -535,9 +570,9 @@
   1.220  
   1.221          @Override
   1.222          protected void generatePrologue() throws IOException {
   1.223 -            out.append("bck2brwsr.registerExtension(function(exports) {\n"
   1.224 +            append("bck2brwsr.registerExtension(function(exports) {\n"
   1.225                             + "  var vm = {};\n");
   1.226 -            out.append("  function link(n, inst) {\n"
   1.227 +            append("  function link(n, inst) {\n"
   1.228                             + "    var cls = n['replace__Ljava_lang_String_2CC']"
   1.229                                                    + "('/', '_').toString();\n"
   1.230                             + "    var dot = n['replace__Ljava_lang_String_2CC']"
   1.231 @@ -550,13 +585,13 @@
   1.232  
   1.233          @Override
   1.234          protected void generateEpilogue() throws IOException {
   1.235 -            out.append("});");
   1.236 +            append("});");
   1.237          }
   1.238  
   1.239          @Override
   1.240          protected String generateClass(String className) throws IOException {
   1.241              if (isExternalClass(className)) {
   1.242 -                out.append("\n").append(assignClass(
   1.243 +                append("\n").append(assignClass(
   1.244                                              className.replace('/', '_')))
   1.245                     .append("function() {\n  return link('")
   1.246                     .append(className)
   1.247 @@ -579,4 +614,16 @@
   1.248              return !extensionClasses.contains(className);
   1.249          }
   1.250      }
   1.251 +    
   1.252 +    private static void lazyReference(Appendable out, String n) throws IOException {
   1.253 +        String cls = n.replace('/', '_');
   1.254 +        String dot = n.replace('/', '.');
   1.255 +        
   1.256 +        out.append("\nvm.").append(cls).append(" = function() {");
   1.257 +        out.append("\n  var instance = arguments.length == 0 || arguments[0] === true;");
   1.258 +        out.append("\n  delete vm.").append(cls).append(";");
   1.259 +        out.append("\n  var c = vm.loadClass('").append(dot).append("');");
   1.260 +        out.append("\n  return vm.").append(cls).append("(instance);");
   1.261 +        out.append("\n}");
   1.262 +    }
   1.263  }