# HG changeset patch # User Jaroslav Tulach # Date 1359128824 -3600 # Node ID efe024e8afd65acdda16190b3b8caf75a81e0bb6 # Parent b670af2aa0f78c66a40a79dcc684074c914daeb5# Parent 608e7a4728fb74cb348f8f84490301bab52261a6 Merge of ServiceLoader capable of loading class and its implementation diff -r b670af2aa0f7 -r efe024e8afd6 emul/compact/src/test/java/org/apidesign/bck2brwsr/compact/tck/ServiceLoaderTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/emul/compact/src/test/java/org/apidesign/bck2brwsr/compact/tck/ServiceLoaderTest.java Fri Jan 25 16:47:04 2013 +0100 @@ -0,0 +1,61 @@ +/** + * Back 2 Browser Bytecode Translator + * Copyright (C) 2012 Jaroslav Tulach + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. Look for COPYING file in the top folder. + * If not, see http://opensource.org/licenses/GPL-2.0. + */ +package org.apidesign.bck2brwsr.compact.tck; + +import java.io.IOException; +import java.util.ServiceLoader; +import org.apidesign.bck2brwsr.vmtest.Compare; +import org.apidesign.bck2brwsr.vmtest.VMTest; +import org.openide.util.lookup.ServiceProvider; +import org.testng.annotations.Factory; + +/** + * + * @author Jaroslav Tulach + */ +public class ServiceLoaderTest { + @Compare//(scripting = false) + public Object findsIOException() { +// delayStart(); + for (IOException e : ServiceLoader.load(IOException.class)) { + return "Found service: " + e.getClass().getName(); + } + return null; + } +/* + @org.apidesign.bck2brwsr.core.JavaScriptBody(args = { "a" }, body = "alert(a);") + private static void alert(String a) { + } + private void delayStart() { + for (int i = 0; i < 10; i++) { + alert("State: " + i); + for (int j = 0; j < 493208409; j++) ; + } + } +*/ + + @Factory + public static Object[] create() { + return VMTest.create(ServiceLoaderTest.class); + } + + + @ServiceProvider(service = IOException.class) + public static class MyException extends IOException { + } +} diff -r b670af2aa0f7 -r efe024e8afd6 emul/mini/src/main/java/java/lang/Character.java --- a/emul/mini/src/main/java/java/lang/Character.java Fri Jan 25 15:47:46 2013 +0100 +++ b/emul/mini/src/main/java/java/lang/Character.java Fri Jan 25 16:47:04 2013 +0100 @@ -2026,7 +2026,7 @@ */ public static boolean isJavaIdentifierPart(int codePoint) { return isJavaIdentifierStart(codePoint) || - ('0' <= codePoint && codePoint <= '9'); + ('0' <= codePoint && codePoint <= '9') || codePoint == '$'; } /** diff -r b670af2aa0f7 -r efe024e8afd6 emul/mini/src/main/java/java/lang/Class.java --- a/emul/mini/src/main/java/java/lang/Class.java Fri Jan 25 15:47:46 2013 +0100 +++ b/emul/mini/src/main/java/java/lang/Class.java Fri Jan 25 16:47:04 2013 +0100 @@ -32,6 +32,7 @@ import java.lang.reflect.Field; import java.lang.reflect.Method; import java.lang.reflect.TypeVariable; +import java.net.URL; import org.apidesign.bck2brwsr.core.JavaScriptBody; import org.apidesign.bck2brwsr.emul.reflect.MethodImpl; @@ -1030,15 +1031,16 @@ * @since JDK1.1 */ public java.net.URL getResource(String name) { - name = resolveName(name); - ClassLoader cl = null; - if (cl==null) { - // A system class. - return ClassLoader.getSystemResource(name); - } - return cl.getResource(name); + InputStream is = getResourceAsStream(name); + return is == null ? null : newResourceURL(URL.class, "res:/" + name, is); } - + + @JavaScriptBody(args = { "url", "spec", "is" }, body = + "var u = url.cnstr(true);\n" + + "u.constructor.cons__VLjava_lang_String_2Ljava_io_InputStream_2.call(u, spec, is);\n" + + "return u;" + ) + private static native URL newResourceURL(Class url, String spec, InputStream is); /** * Add a package name prefix if the name is not absolute Remove leading "/" diff -r b670af2aa0f7 -r efe024e8afd6 emul/mini/src/main/java/java/lang/ClassLoader.java --- a/emul/mini/src/main/java/java/lang/ClassLoader.java Fri Jan 25 15:47:46 2013 +0100 +++ b/emul/mini/src/main/java/java/lang/ClassLoader.java Fri Jan 25 16:47:04 2013 +0100 @@ -703,7 +703,7 @@ public static Enumeration getSystemResources(String name) throws IOException { - ClassLoader system = getSystemClassLoader(); + ClassLoader system = null; // getSystemClassLoader(); if (system == null) { return getBootstrapResources(name); } @@ -874,7 +874,29 @@ } private static Enumeration getBootstrapResources(String name) { - throw new UnsupportedOperationException(); + URL u = Object.class.getResource("/" + name); + return new OneOrZeroEnum(u); + } + + private static class OneOrZeroEnum implements Enumeration { + private URL u; + + public OneOrZeroEnum(URL u) { + this.u = u; + } + + public boolean hasMoreElements() { + return u != null; + } + + public URL nextElement() { + URL r = u; + if (r == null) { + throw new NoSuchElementException(); + } + u = null; + return r; + } } private static class CompoundEnumeration implements Enumeration { diff -r b670af2aa0f7 -r efe024e8afd6 emul/mini/src/main/java/java/net/URL.java --- a/emul/mini/src/main/java/java/net/URL.java Fri Jan 25 15:47:46 2013 +0100 +++ b/emul/mini/src/main/java/java/net/URL.java Fri Jan 25 16:47:04 2013 +0100 @@ -29,6 +29,7 @@ import java.io.InputStream; import org.apidesign.bck2brwsr.core.JavaScriptBody; + /** * Class URL represents a Uniform Resource * Locator, a pointer to a "resource" on the World @@ -212,6 +213,9 @@ * @serial */ private int hashCode = -1; + + /** input stream associated with the URL */ + private InputStream is; /** * Creates a URL object from the specified @@ -421,6 +425,11 @@ public URL(String spec) throws MalformedURLException { this(null, spec); } + + private URL(String spec, InputStream is) throws MalformedURLException { + this(null, spec); + this.is = is; + } /** * Creates a URL by parsing the given spec within a specified context. @@ -950,8 +959,10 @@ * @see java.net.URLConnection#getInputStream() */ public final InputStream openStream() throws java.io.IOException { + if (is != null) { + return is; + } throw new IOException(); -// return openConnection().getInputStream(); } /** @@ -1006,7 +1017,6 @@ } } - class Parts { String path, query, ref; diff -r b670af2aa0f7 -r efe024e8afd6 vm/src/main/java/org/apidesign/vm4brwsr/ByteCodeToJavaScript.java --- a/vm/src/main/java/org/apidesign/vm4brwsr/ByteCodeToJavaScript.java Fri Jan 25 15:47:46 2013 +0100 +++ b/vm/src/main/java/org/apidesign/vm4brwsr/ByteCodeToJavaScript.java Fri Jan 25 16:47:04 2013 +0100 @@ -270,6 +270,7 @@ int lastStackFrame = -1; TrapData[] previousTrap = null; + boolean wide = false; out.append("\n var gt = 0;\n for(;;) switch(gt) {\n"); for (int i = 0; i < byteCodes.length; i++) { @@ -295,7 +296,7 @@ out.append("try {"); previousTrap = trap.current(); } - final int c = readByte(byteCodes, i); + final int c = readUByte(byteCodes, i); switch (c) { case opc_aload_0: emit(out, "var @1 = @2;", smapper.pushA(), lmapper.getA(0)); @@ -358,61 +359,91 @@ emit(out, "var @1 = @2;", smapper.pushD(), lmapper.getD(3)); break; case opc_iload: { - final int indx = readByte(byteCodes, ++i); + ++i; + final int indx = wide ? readUShort(byteCodes, i++) + : readUByte(byteCodes, i); + wide = false; emit(out, "var @1 = @2;", smapper.pushI(), lmapper.getI(indx)); break; } case opc_lload: { - final int indx = readByte(byteCodes, ++i); + ++i; + final int indx = wide ? readUShort(byteCodes, i++) + : readUByte(byteCodes, i); + wide = false; emit(out, "var @1 = @2;", smapper.pushL(), lmapper.getL(indx)); break; } case opc_fload: { - final int indx = readByte(byteCodes, ++i); + ++i; + final int indx = wide ? readUShort(byteCodes, i++) + : readUByte(byteCodes, i); + wide = false; emit(out, "var @1 = @2;", smapper.pushF(), lmapper.getF(indx)); break; } case opc_dload: { - final int indx = readByte(byteCodes, ++i); + ++i; + final int indx = wide ? readUShort(byteCodes, i++) + : readUByte(byteCodes, i); + wide = false; emit(out, "var @1 = @2;", smapper.pushD(), lmapper.getD(indx)); break; } case opc_aload: { - final int indx = readByte(byteCodes, ++i); + ++i; + final int indx = wide ? readUShort(byteCodes, i++) + : readUByte(byteCodes, i); + wide = false; emit(out, "var @1 = @2;", smapper.pushA(), lmapper.getA(indx)); break; } case opc_istore: { - final int indx = readByte(byteCodes, ++i); + ++i; + final int indx = wide ? readUShort(byteCodes, i++) + : readUByte(byteCodes, i); + wide = false; emit(out, "var @1 = @2;", lmapper.setI(indx), smapper.popI()); break; } case opc_lstore: { - final int indx = readByte(byteCodes, ++i); + ++i; + final int indx = wide ? readUShort(byteCodes, i++) + : readUByte(byteCodes, i); + wide = false; emit(out, "var @1 = @2;", lmapper.setL(indx), smapper.popL()); break; } case opc_fstore: { - final int indx = readByte(byteCodes, ++i); + ++i; + final int indx = wide ? readUShort(byteCodes, i++) + : readUByte(byteCodes, i); + wide = false; emit(out, "var @1 = @2;", lmapper.setF(indx), smapper.popF()); break; } case opc_dstore: { - final int indx = readByte(byteCodes, ++i); + ++i; + final int indx = wide ? readUShort(byteCodes, i++) + : readUByte(byteCodes, i); + wide = false; emit(out, "var @1 = @2;", lmapper.setD(indx), smapper.popD()); break; } case opc_astore: { - final int indx = readByte(byteCodes, ++i); + ++i; + final int indx = wide ? readUShort(byteCodes, i++) + : readUByte(byteCodes, i); + wide = false; emit(out, "var @1 = @2;", lmapper.setA(indx), smapper.popA()); break; @@ -588,8 +619,13 @@ emit(out, "@1 >>>= @2;", smapper.getL(1), smapper.popI()); break; case opc_iinc: { - final int varIndx = readByte(byteCodes, ++i); - final int incrBy = byteCodes[++i]; + ++i; + final int varIndx = wide ? readUShort(byteCodes, i++) + : readUByte(byteCodes, i); + ++i; + final int incrBy = wide ? readIntArg(byteCodes, i++) + : byteCodes[i]; + wide = false; if (incrBy == 1) { emit(out, "@1++;", lmapper.getI(varIndx)); } else { @@ -713,7 +749,7 @@ emit(out, "var @1 = 5;", smapper.pushI()); break; case opc_ldc: { - int indx = readByte(byteCodes, ++i); + int indx = readUByte(byteCodes, ++i); String v = encodeConstant(indx); int type = VarType.fromConstantType(jc.getTag(indx)); emit(out, "var @1 = @2;", smapper.pushT(type), v); @@ -896,7 +932,7 @@ break; } case opc_newarray: - int atype = readByte(byteCodes, ++i); + int atype = readUByte(byteCodes, ++i); String jvmType; switch (atype) { case 4: jvmType = "[Z"; break; @@ -929,7 +965,7 @@ int type = readIntArg(byteCodes, i); i += 2; String typeName = jc.getClassName(type); - int dim = readByte(byteCodes, ++i); + int dim = readUByte(byteCodes, ++i); StringBuilder dims = new StringBuilder(); dims.append('['); for (int d = 0; d < dim; d++) { @@ -1004,16 +1040,16 @@ break; } case opc_dup2: { - if (smapper.get(0).isCategory2()) { - final Variable v = smapper.get(0); + final Variable vi1 = smapper.get(0); + + if (vi1.isCategory2()) { emit(out, "var @1 = @2;", - smapper.pushT(v.getType()), v); + smapper.pushT(vi1.getType()), vi1); } else { - final Variable v1 = smapper.get(0); - final Variable v2 = smapper.get(1); + final Variable vi2 = smapper.get(1); emit(out, "var @1 = @2, @3 = @4;", - smapper.pushT(v2.getType()), v2, - smapper.pushT(v1.getType()), v1); + smapper.pushT(vi2.getType()), vi2, + smapper.pushT(vi1.getType()), vi1); } break; } @@ -1028,10 +1064,11 @@ vo1, vi1, vo2, vi2, vo3, vo1); break; } - case opc_dup_x2: { - if (smapper.get(1).isCategory2()) { - final Variable vi1 = smapper.pop(); - final Variable vi2 = smapper.pop(); + case opc_dup2_x1: { + final Variable vi1 = smapper.pop(); + final Variable vi2 = smapper.pop(); + + if (vi1.isCategory2()) { final Variable vo3 = smapper.pushT(vi1.getType()); final Variable vo2 = smapper.pushT(vi2.getType()); final Variable vo1 = smapper.pushT(vi1.getType()); @@ -1039,8 +1076,32 @@ emit(out, "var @1 = @2, @3 = @4, @5 = @6;", vo1, vi1, vo2, vi2, vo3, vo1); } else { - final Variable vi1 = smapper.pop(); - final Variable vi2 = smapper.pop(); + final Variable vi3 = smapper.pop(); + final Variable vo5 = smapper.pushT(vi2.getType()); + final Variable vo4 = smapper.pushT(vi1.getType()); + final Variable vo3 = smapper.pushT(vi3.getType()); + final Variable vo2 = smapper.pushT(vi2.getType()); + final Variable vo1 = smapper.pushT(vi1.getType()); + + emit(out, "var @1 = @2, @3 = @4, @5 = @6,", + vo1, vi1, vo2, vi2, vo3, vi3); + emit(out, " @1 = @2, @3 = @4;", + vo4, vo1, vo5, vo2); + } + break; + } + case opc_dup_x2: { + final Variable vi1 = smapper.pop(); + final Variable vi2 = smapper.pop(); + + if (vi2.isCategory2()) { + final Variable vo3 = smapper.pushT(vi1.getType()); + final Variable vo2 = smapper.pushT(vi2.getType()); + final Variable vo1 = smapper.pushT(vi1.getType()); + + emit(out, "var @1 = @2, @3 = @4, @5 = @6;", + vo1, vi1, vo2, vi2, vo3, vo1); + } else { final Variable vi3 = smapper.pop(); final Variable vo4 = smapper.pushT(vi1.getType()); final Variable vo3 = smapper.pushT(vi3.getType()); @@ -1052,6 +1113,76 @@ } break; } + case opc_dup2_x2: { + final Variable vi1 = smapper.pop(); + final Variable vi2 = smapper.pop(); + + if (vi1.isCategory2()) { + if (vi2.isCategory2()) { + final Variable vo3 = smapper.pushT(vi1.getType()); + final Variable vo2 = smapper.pushT(vi2.getType()); + final Variable vo1 = smapper.pushT(vi1.getType()); + + emit(out, "var @1 = @2, @3 = @4, @5 = @6;", + vo1, vi1, vo2, vi2, vo3, vo1); + } else { + final Variable vi3 = smapper.pop(); + final Variable vo4 = smapper.pushT(vi1.getType()); + final Variable vo3 = smapper.pushT(vi3.getType()); + final Variable vo2 = smapper.pushT(vi2.getType()); + final Variable vo1 = smapper.pushT(vi1.getType()); + + emit(out, "var @1 = @2, @3 = @4, @5 = @6, @7 = @8;", + vo1, vi1, vo2, vi2, vo3, vi3, vo4, vo1); + } + } else { + final Variable vi3 = smapper.pop(); + + if (vi3.isCategory2()) { + final Variable vo5 = smapper.pushT(vi2.getType()); + final Variable vo4 = smapper.pushT(vi1.getType()); + final Variable vo3 = smapper.pushT(vi3.getType()); + final Variable vo2 = smapper.pushT(vi2.getType()); + final Variable vo1 = smapper.pushT(vi1.getType()); + + emit(out, "var @1 = @2, @3 = @4, @5 = @6,", + vo1, vi1, vo2, vi2, vo3, vi3); + emit(out, " @1 = @2, @3 = @4;", + vo4, vo1, vo5, vo2); + } else { + final Variable vi4 = smapper.pop(); + final Variable vo6 = smapper.pushT(vi2.getType()); + final Variable vo5 = smapper.pushT(vi1.getType()); + final Variable vo4 = smapper.pushT(vi4.getType()); + final Variable vo3 = smapper.pushT(vi3.getType()); + final Variable vo2 = smapper.pushT(vi2.getType()); + final Variable vo1 = smapper.pushT(vi1.getType()); + + emit(out, "var @1 = @2, @3 = @4, @5 = @6, @7 = @8,", + vo1, vi1, vo2, vi2, vo3, vi3, vo4, vi4); + emit(out, " @1 = @2, @3 = @4;", + vo5, vo1, vo6, vo2); + } + } + break; + } + case opc_swap: { + final Variable vi1 = smapper.get(0); + final Variable vi2 = smapper.get(1); + + if (vi1.getType() == vi2.getType()) { + final Variable tmp = smapper.pushT(vi1.getType()); + + emit(out, "var @1 = @2, @2 = @3, @3 = @1;", + tmp, vi1, vi2); + smapper.pop(1); + } else { + smapper.pop(2); + smapper.pushT(vi1.getType()); + smapper.pushT(vi2.getType()); + } + break; + } case opc_bipush: emit(out, "var @1 = @2;", smapper.pushI(), Integer.toString(byteCodes[++i])); @@ -1154,7 +1285,12 @@ break; } + case opc_wide: + wide = true; + break; + default: { + wide = false; emit(out, "throw 'unknown bytecode @1';", Integer.toString(c)); } @@ -1162,7 +1298,7 @@ if (debug(" //")) { for (int j = prev; j <= i; j++) { out.append(" "); - final int cc = readByte(byteCodes, j); + final int cc = readUByte(byteCodes, j); out.append(Integer.toString(cc)); } } @@ -1198,10 +1334,15 @@ final int a = byteCodes[offsetInstruction + 3]; return (d & 0xff000000) | (c & 0xff0000) | (b & 0xff00) | (a & 0xff); } - private int readByte(byte[] byteCodes, int offsetInstruction) { + private int readUByte(byte[] byteCodes, int offsetInstruction) { return byteCodes[offsetInstruction] & 0xff; } - + + private int readUShort(byte[] byteCodes, int offsetInstruction) { + return ((byteCodes[offsetInstruction] & 0xff) << 8) + | (byteCodes[offsetInstruction + 1] & 0xff); + } + private static void countArgs(String descriptor, char[] returnType, StringBuilder sig, StringBuilder cnt) { int i = 0; Boolean count = null; diff -r b670af2aa0f7 -r efe024e8afd6 vm/src/main/java/org/apidesign/vm4brwsr/VarType.java --- a/vm/src/main/java/org/apidesign/vm4brwsr/VarType.java Fri Jan 25 15:47:46 2013 +0100 +++ b/vm/src/main/java/org/apidesign/vm4brwsr/VarType.java Fri Jan 25 16:47:04 2013 +0100 @@ -45,13 +45,13 @@ return VarType.DOUBLE; case RuntimeConstants.ITEM_Long: return VarType.LONG; + case RuntimeConstants.ITEM_Null: + case RuntimeConstants.ITEM_InitObject: case RuntimeConstants.ITEM_Object: + case RuntimeConstants.ITEM_NewObject: return VarType.REFERENCE; case RuntimeConstants.ITEM_Bogus: - case RuntimeConstants.ITEM_Null: - case RuntimeConstants.ITEM_InitObject: - case RuntimeConstants.ITEM_NewObject: /* unclear how to handle for now */ default: throw new IllegalStateException("Unhandled stack map type");