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 }