1.1 --- a/src/main/java/org/apidesign/java4browser/ByteCodeToJavaScript.java Sun Sep 16 07:28:57 2012 +0200
1.2 +++ b/src/main/java/org/apidesign/java4browser/ByteCodeToJavaScript.java Sun Sep 16 18:35:16 2012 +0200
1.3 @@ -24,7 +24,6 @@
1.4 import org.netbeans.modules.classfile.CPClassInfo;
1.5 import org.netbeans.modules.classfile.CPEntry;
1.6 import org.netbeans.modules.classfile.CPFieldInfo;
1.7 -import org.netbeans.modules.classfile.CPLongInfo;
1.8 import org.netbeans.modules.classfile.CPMethodInfo;
1.9 import org.netbeans.modules.classfile.ClassFile;
1.10 import org.netbeans.modules.classfile.Code;
1.11 @@ -57,6 +56,8 @@
1.12 for (Method m : jc.getMethods()) {
1.13 if (m.isStatic()) {
1.14 compiler.generateStaticMethod(m);
1.15 + } else {
1.16 + compiler.generateInstanceMethod(m);
1.17 }
1.18 }
1.19 for (Variable v : jc.getVariables()) {
1.20 @@ -64,20 +65,29 @@
1.21 compiler.generateStaticField(v);
1.22 }
1.23 }
1.24 + out.append("function java_lang_Object_consV(self){}\n"); // XXX temporary
1.25 +
1.26 + out.append("\nfunction ").append(jc.getName().getExternalName().replace('.', '_'));
1.27 + out.append("() {");
1.28 + for (Method m : jc.getMethods()) {
1.29 + if (!m.isStatic()) {
1.30 +
1.31 + }
1.32 + }
1.33 + for (Variable v : jc.getVariables()) {
1.34 + if (!v.isStatic()) {
1.35 + out.append("\n this." + v.getName() + " = 0;");
1.36 + }
1.37 + }
1.38 + out.append("\n}");
1.39 }
1.40 private void generateStaticMethod(Method m) throws IOException {
1.41 out.append("\nfunction ").append(
1.42 jc.getName().getExternalName().replace('.', '_')
1.43 - ).append('_').append(
1.44 - m.getName()
1.45 - );
1.46 - out.append(m.getReturnType());
1.47 - List<Parameter> args = m.getParameters();
1.48 - for (Parameter t : args) {
1.49 - out.append(t.getDescriptor());
1.50 - }
1.51 + ).append('_').append(findMethodName(m));
1.52 out.append('(');
1.53 String space = "";
1.54 + List<Parameter> args = m.getParameters();
1.55 for (int index = 0, i = 0; i < args.size(); i++) {
1.56 out.append(space);
1.57 out.append("arg").append(String.valueOf(index));
1.58 @@ -96,6 +106,37 @@
1.59 out.append(" var ");
1.60 out.append("arg").append(String.valueOf(i)).append(";\n");
1.61 }
1.62 + out.append(" var stack = new Array(");
1.63 + out.append(Integer.toString(code.getMaxStack()));
1.64 + out.append(");\n");
1.65 + produceCode(code.getByteCodes());
1.66 + out.append("}");
1.67 + }
1.68 +
1.69 + private void generateInstanceMethod(Method m) throws IOException {
1.70 + out.append("\nfunction ").append(
1.71 + jc.getName().getExternalName().replace('.', '_')
1.72 + ).append('_').append(findMethodName(m));
1.73 + out.append("(arg0");
1.74 + String space = ",";
1.75 + List<Parameter> args = m.getParameters();
1.76 + for (int index = 1, i = 0; i < args.size(); i++) {
1.77 + out.append(space);
1.78 + out.append("arg").append(String.valueOf(index));
1.79 + final String desc = args.get(i).getDescriptor();
1.80 + if ("D".equals(desc) || "J".equals(desc)) {
1.81 + index += 2;
1.82 + } else {
1.83 + index++;
1.84 + }
1.85 + }
1.86 + out.append(") {").append("\n");
1.87 + final Code code = m.getCode();
1.88 + int len = code.getMaxLocals();
1.89 + for (int index = args.size(), i = args.size(); i < len; i++) {
1.90 + out.append(" var ");
1.91 + out.append("arg").append(String.valueOf(i + 1)).append(";\n");
1.92 + }
1.93 out.append(";\n var stack = new Array(");
1.94 out.append(Integer.toString(code.getMaxStack()));
1.95 out.append(");\n");
1.96 @@ -104,10 +145,10 @@
1.97 }
1.98
1.99 private void produceCode(byte[] byteCodes) throws IOException {
1.100 - out.append("\nvar gt = 0;\nfor(;;) switch(gt) {\n");
1.101 + out.append("\n var gt = 0;\n for(;;) switch(gt) {\n");
1.102 for (int i = 0; i < byteCodes.length; i++) {
1.103 int prev = i;
1.104 - out.append(" case " + i).append(": ");
1.105 + out.append(" case " + i).append(": ");
1.106 final int c = (byteCodes[i] + 256) % 256;
1.107 switch (c) {
1.108 case bc_aload_0:
1.109 @@ -223,10 +264,14 @@
1.110 }
1.111 break;
1.112 }
1.113 + case bc_return:
1.114 + out.append("return;");
1.115 + break;
1.116 case bc_ireturn:
1.117 case bc_lreturn:
1.118 case bc_freturn:
1.119 case bc_dreturn:
1.120 + case bc_areturn:
1.121 out.append("return stack.pop();");
1.122 break;
1.123 case bc_i2l:
1.124 @@ -316,41 +361,18 @@
1.125 i += 2;
1.126 break;
1.127 }
1.128 - case bc_invokestatic: {
1.129 - int methodIndex = readIntArg(byteCodes, i);
1.130 - CPMethodInfo mi = (CPMethodInfo) jc.getConstantPool().get(methodIndex);
1.131 - boolean[] hasReturn = { false };
1.132 - StringBuilder signature = new StringBuilder();
1.133 - int cnt = countArgs(mi.getDescriptor(), hasReturn, signature);
1.134 -
1.135 - if (hasReturn[0]) {
1.136 - out.append("stack.push(");
1.137 - }
1.138 - out.append(mi.getClassName().getInternalName().replace('/', '_'));
1.139 - out.append('_');
1.140 - out.append(mi.getName());
1.141 - out.append(signature.toString());
1.142 - out.append('(');
1.143 - String sep = "";
1.144 - for (int j = 0; j < cnt; j++) {
1.145 - out.append(sep);
1.146 - out.append("stack.pop()");
1.147 - sep = ", ";
1.148 - }
1.149 - out.append(")");
1.150 - if (hasReturn[0]) {
1.151 - out.append(")");
1.152 - }
1.153 - out.append(";");
1.154 - i += 2;
1.155 + case bc_invokespecial:
1.156 + i = invokeStaticMethod(byteCodes, i, false);
1.157 break;
1.158 - }
1.159 + case bc_invokestatic:
1.160 + i = invokeStaticMethod(byteCodes, i, true);
1.161 + break;
1.162 case bc_new: {
1.163 int indx = readIntArg(byteCodes, i);
1.164 CPClassInfo ci = jc.getConstantPool().getClass(indx);
1.165 out.append("stack.push(");
1.166 out.append("new ").append(ci.getClassName().getExternalName().replace('.','_'));
1.167 - out.append("());");
1.168 + out.append(");");
1.169 i += 2;
1.170 break;
1.171 }
1.172 @@ -360,14 +382,6 @@
1.173 case bc_bipush:
1.174 out.append("stack.push(" + byteCodes[++i] + ");");
1.175 break;
1.176 - case bc_invokevirtual:
1.177 - case bc_invokespecial: {
1.178 - int indx = readIntArg(byteCodes, i);
1.179 - CPMethodInfo mi = (CPMethodInfo) jc.getConstantPool().get(indx);
1.180 - out.append("{ var tmp = stack.pop(); tmp." + mi.getMethodName() + "(); }");
1.181 - i += 2;
1.182 - break;
1.183 - }
1.184 case bc_getfield: {
1.185 int indx = readIntArg(byteCodes, i);
1.186 CPFieldInfo fi = (CPFieldInfo) jc.getConstantPool().get(indx);
1.187 @@ -391,6 +405,14 @@
1.188 i += 2;
1.189 break;
1.190 }
1.191 + case bc_putfield: {
1.192 + int indx = readIntArg(byteCodes, i);
1.193 + CPFieldInfo fi = (CPFieldInfo) jc.getConstantPool().get(indx);
1.194 + out.append("{ var v = stack.pop(); stack.pop().")
1.195 + .append(fi.getFieldName()).append(" = v; }");
1.196 + i += 2;
1.197 + break;
1.198 + }
1.199
1.200 }
1.201 out.append(" /*");
1.202 @@ -401,7 +423,7 @@
1.203 }
1.204 out.append("*/\n");
1.205 }
1.206 - out.append("}\n");
1.207 + out.append(" }\n");
1.208 }
1.209
1.210 private int generateIf(byte[] byteCodes, int i, final String test) throws IOException {
1.211 @@ -421,6 +443,7 @@
1.212 int cnt = 0;
1.213 int i = 0;
1.214 Boolean count = null;
1.215 + int firstPos = sig.length();
1.216 while (i < descriptor.length()) {
1.217 char ch = descriptor.charAt(i++);
1.218 switch (ch) {
1.219 @@ -443,13 +466,13 @@
1.220 sig.append(ch);
1.221 } else {
1.222 hasReturnType[0] = true;
1.223 - sig.insert(0, ch);
1.224 + sig.insert(firstPos, ch);
1.225 }
1.226 continue;
1.227 case 'V':
1.228 assert !count;
1.229 hasReturnType[0] = false;
1.230 - sig.insert(0, 'V');
1.231 + sig.insert(firstPos, 'V');
1.232 continue;
1.233 case 'L':
1.234 i = descriptor.indexOf(';', i);
1.235 @@ -474,4 +497,63 @@
1.236 .append(jc.getName().getExternalName().replace('.', '_'))
1.237 .append('_').append(v.getName()).append(" = 0;");
1.238 }
1.239 +
1.240 + private String findMethodName(Method m) {
1.241 + StringBuilder out = new StringBuilder();
1.242 + if ("<init>".equals(m.getName())) { // NOI18N
1.243 + out.append("consV"); // NOI18N
1.244 + } else {
1.245 + out.append(m.getName());
1.246 + out.append(m.getReturnType());
1.247 + }
1.248 + List<Parameter> args = m.getParameters();
1.249 + for (Parameter t : args) {
1.250 + out.append(t.getDescriptor());
1.251 + }
1.252 + return out.toString();
1.253 + }
1.254 +
1.255 + private String findMethodName(CPMethodInfo mi, int[] cnt, boolean[] hasReturn) {
1.256 + StringBuilder name = new StringBuilder();
1.257 + if ("<init>".equals(mi.getName())) { // NOI18N
1.258 + name.append("cons"); // NOI18N
1.259 + } else {
1.260 + name.append(mi.getName());
1.261 + }
1.262 + cnt[0] = countArgs(mi.getDescriptor(), hasReturn, name);
1.263 + return name.toString();
1.264 + }
1.265 +
1.266 + private int invokeStaticMethod(byte[] byteCodes, int i, boolean isStatic)
1.267 + throws IOException {
1.268 + int methodIndex = readIntArg(byteCodes, i);
1.269 + CPMethodInfo mi = (CPMethodInfo) jc.getConstantPool().get(methodIndex);
1.270 + boolean[] hasReturn = { false };
1.271 + int[] cnt = { 0 };
1.272 + String mn = findMethodName(mi, cnt, hasReturn);
1.273 + if (hasReturn[0]) {
1.274 + out.append("stack.push(");
1.275 + }
1.276 + out.append(mi.getClassName().getInternalName().replace('/', '_'));
1.277 + out.append('_');
1.278 + out.append(mn);
1.279 + out.append('(');
1.280 + String sep = "";
1.281 + if (!isStatic) {
1.282 + out.append("stack.pop()");
1.283 + sep = ", ";
1.284 + }
1.285 + for (int j = 0; j < cnt[0]; j++) {
1.286 + out.append(sep);
1.287 + out.append("stack.pop()");
1.288 + sep = ", ";
1.289 + }
1.290 + out.append(")");
1.291 + if (hasReturn[0]) {
1.292 + out.append(")");
1.293 + }
1.294 + out.append(";");
1.295 + i += 2;
1.296 + return i;
1.297 + }
1.298 }