Thu, 08 Aug 2013 16:38:32 +0530
8022524: Memory leaks in nashorn sources and tests found by jhat analysis
Reviewed-by: attila, hannesw
1.1 --- a/make/project.properties Wed Aug 07 16:38:44 2013 +0200 1.2 +++ b/make/project.properties Thu Aug 08 16:38:32 2013 +0530 1.3 @@ -223,9 +223,9 @@ 1.4 run.test.user.country=TR 1.5 1.6 # -XX:+PrintCompilation -XX:+UnlockDiagnosticVMOptions -XX:+PrintNMethods 1.7 -run.test.jvmargs.main=-server -Xmx${run.test.xmx} -XX:+TieredCompilation -ea -Dfile.encoding=UTF-8 -Duser.language=${run.test.user.language} -Duser.country=${run.test.user.country} 1.8 +run.test.jvmargs.main=-server -Xmx${run.test.xmx} -XX:+TieredCompilation -ea -Dfile.encoding=UTF-8 -Duser.language=${run.test.user.language} -Duser.country=${run.test.user.country} -XX:+HeapDumpOnOutOfMemoryError 1.9 1.10 -#-XX:+HeapDumpOnOutOfMemoryError -XX:-UseCompressedKlassPointers -XX:+PrintHeapAtGC -XX:ClassMetaspaceSize=300M 1.11 +#-XX:-UseCompressedKlassPointers -XX:+PrintHeapAtGC -XX:ClassMetaspaceSize=300M 1.12 run.test.jvmargs.octane.main=-Xms${run.test.xms} ${run.test.jvmargs.main} 1.13 1.14 run.test.jvmsecurityargs=-Xverify:all -Djava.security.properties=${basedir}/make/java.security.override -Djava.security.manager -Djava.security.policy=${basedir}/build/nashorn.policy
2.1 --- a/src/jdk/nashorn/internal/codegen/CompileUnit.java Wed Aug 07 16:38:44 2013 +0200 2.2 +++ b/src/jdk/nashorn/internal/codegen/CompileUnit.java Thu Aug 08 16:38:32 2013 +0530 2.3 @@ -33,7 +33,7 @@ 2.4 private final String className; 2.5 2.6 /** Current class generator */ 2.7 - private final ClassEmitter classEmitter; 2.8 + private ClassEmitter classEmitter; 2.9 2.10 private long weight; 2.11 2.12 @@ -64,7 +64,11 @@ 2.13 * @param clazz class with code for this compile unit 2.14 */ 2.15 void setCode(final Class<?> clazz) { 2.16 + clazz.getClass(); // null check 2.17 this.clazz = clazz; 2.18 + // Revisit this - refactor to avoid null-ed out non-final fields 2.19 + // null out emitter 2.20 + this.classEmitter = null; 2.21 } 2.22 2.23 /**
3.1 --- a/src/jdk/nashorn/internal/objects/Global.java Wed Aug 07 16:38:44 2013 +0200 3.2 +++ b/src/jdk/nashorn/internal/objects/Global.java Thu Aug 08 16:38:32 2013 +0530 3.3 @@ -41,6 +41,8 @@ 3.4 import java.util.LinkedHashMap; 3.5 import java.util.List; 3.6 import java.util.Map; 3.7 +import java.util.concurrent.Callable; 3.8 +import java.util.concurrent.ConcurrentHashMap; 3.9 import jdk.internal.dynalink.linker.GuardedInvocation; 3.10 import jdk.internal.dynalink.linker.LinkRequest; 3.11 import jdk.nashorn.internal.objects.annotations.Attribute; 3.12 @@ -72,8 +74,8 @@ 3.13 */ 3.14 @ScriptClass("Global") 3.15 public final class Global extends ScriptObject implements GlobalObject, Scope { 3.16 - private static final InvokeByName TO_STRING = new InvokeByName("toString", ScriptObject.class); 3.17 - private static final InvokeByName VALUE_OF = new InvokeByName("valueOf", ScriptObject.class); 3.18 + private final InvokeByName TO_STRING = new InvokeByName("toString", ScriptObject.class); 3.19 + private final InvokeByName VALUE_OF = new InvokeByName("valueOf", ScriptObject.class); 3.20 3.21 /** ECMA 15.1.2.2 parseInt (string , radix) */ 3.22 @Property(attributes = Attribute.NOT_ENUMERABLE) 3.23 @@ -709,6 +711,35 @@ 3.24 classCache.put(source, new SoftReference<Class<?>>(clazz)); 3.25 } 3.26 3.27 + private static <T> T getLazilyCreatedValue(final Object key, final Callable<T> creator, final Map<Object, T> map) { 3.28 + final T obj = map.get(key); 3.29 + if (obj != null) { 3.30 + return obj; 3.31 + } 3.32 + 3.33 + try { 3.34 + final T newObj = creator.call(); 3.35 + final T existingObj = map.putIfAbsent(key, newObj); 3.36 + return existingObj != null ? existingObj : newObj; 3.37 + } catch (final Exception exp) { 3.38 + throw new RuntimeException(exp); 3.39 + } 3.40 + } 3.41 + 3.42 + private final Map<Object, InvokeByName> namedInvokers = new ConcurrentHashMap<>(); 3.43 + 3.44 + @Override 3.45 + public InvokeByName getInvokeByName(final Object key, final Callable<InvokeByName> creator) { 3.46 + return getLazilyCreatedValue(key, creator, namedInvokers); 3.47 + } 3.48 + 3.49 + private final Map<Object, MethodHandle> dynamicInvokers = new ConcurrentHashMap<>(); 3.50 + 3.51 + @Override 3.52 + public MethodHandle getDynamicInvoker(final Object key, final Callable<MethodHandle> creator) { 3.53 + return getLazilyCreatedValue(key, creator, dynamicInvokers); 3.54 + } 3.55 + 3.56 /** 3.57 * This is the eval used when 'indirect' eval call is made. 3.58 *
4.1 --- a/src/jdk/nashorn/internal/objects/NativeArray.java Wed Aug 07 16:38:44 2013 +0200 4.2 +++ b/src/jdk/nashorn/internal/objects/NativeArray.java Thu Aug 08 16:38:32 2013 +0530 4.3 @@ -39,6 +39,7 @@ 4.4 import java.util.Comparator; 4.5 import java.util.Iterator; 4.6 import java.util.List; 4.7 +import java.util.concurrent.Callable; 4.8 import jdk.nashorn.api.scripting.ScriptObjectMirror; 4.9 import jdk.nashorn.internal.objects.annotations.Attribute; 4.10 import jdk.nashorn.internal.objects.annotations.Constructor; 4.11 @@ -68,20 +69,88 @@ 4.12 */ 4.13 @ScriptClass("Array") 4.14 public final class NativeArray extends ScriptObject { 4.15 - private static final InvokeByName JOIN = new InvokeByName("join", ScriptObject.class); 4.16 + private static final Object JOIN = new Object(); 4.17 + private static final Object EVERY_CALLBACK_INVOKER = new Object(); 4.18 + private static final Object SOME_CALLBACK_INVOKER = new Object(); 4.19 + private static final Object FOREACH_CALLBACK_INVOKER = new Object(); 4.20 + private static final Object MAP_CALLBACK_INVOKER = new Object(); 4.21 + private static final Object FILTER_CALLBACK_INVOKER = new Object(); 4.22 + private static final Object REDUCE_CALLBACK_INVOKER = new Object(); 4.23 + private static final Object CALL_CMP = new Object(); 4.24 + private static final Object TO_LOCALE_STRING = new Object(); 4.25 4.26 - private static final MethodHandle EVERY_CALLBACK_INVOKER = createIteratorCallbackInvoker(boolean.class); 4.27 - private static final MethodHandle SOME_CALLBACK_INVOKER = createIteratorCallbackInvoker(boolean.class); 4.28 - private static final MethodHandle FOREACH_CALLBACK_INVOKER = createIteratorCallbackInvoker(void.class); 4.29 - private static final MethodHandle MAP_CALLBACK_INVOKER = createIteratorCallbackInvoker(Object.class); 4.30 - private static final MethodHandle FILTER_CALLBACK_INVOKER = createIteratorCallbackInvoker(boolean.class); 4.31 + private static InvokeByName getJOIN() { 4.32 + return Global.instance().getInvokeByName(JOIN, 4.33 + new Callable<InvokeByName>() { 4.34 + @Override 4.35 + public InvokeByName call() { 4.36 + return new InvokeByName("join", ScriptObject.class); 4.37 + } 4.38 + }); 4.39 + } 4.40 4.41 - private static final MethodHandle REDUCE_CALLBACK_INVOKER = Bootstrap.createDynamicInvoker("dyn:call", Object.class, 4.42 - Object.class, Undefined.class, Object.class, Object.class, long.class, Object.class); 4.43 - private static final MethodHandle CALL_CMP = Bootstrap.createDynamicInvoker("dyn:call", double.class, 4.44 - ScriptFunction.class, Object.class, Object.class, Object.class); 4.45 + private static MethodHandle createIteratorCallbackInvoker(final Object key, final Class<?> rtype) { 4.46 + return Global.instance().getDynamicInvoker(key, 4.47 + new Callable<MethodHandle>() { 4.48 + @Override 4.49 + public MethodHandle call() { 4.50 + return Bootstrap.createDynamicInvoker("dyn:call", rtype, Object.class, Object.class, Object.class, 4.51 + long.class, Object.class); 4.52 + } 4.53 + }); 4.54 + } 4.55 4.56 - private static final InvokeByName TO_LOCALE_STRING = new InvokeByName("toLocaleString", ScriptObject.class, String.class); 4.57 + private static MethodHandle getEVERY_CALLBACK_INVOKER() { 4.58 + return createIteratorCallbackInvoker(EVERY_CALLBACK_INVOKER, boolean.class); 4.59 + } 4.60 + 4.61 + private static MethodHandle getSOME_CALLBACK_INVOKER() { 4.62 + return createIteratorCallbackInvoker(SOME_CALLBACK_INVOKER, boolean.class); 4.63 + } 4.64 + 4.65 + private static MethodHandle getFOREACH_CALLBACK_INVOKER() { 4.66 + return createIteratorCallbackInvoker(FOREACH_CALLBACK_INVOKER, void.class); 4.67 + } 4.68 + 4.69 + private static MethodHandle getMAP_CALLBACK_INVOKER() { 4.70 + return createIteratorCallbackInvoker(MAP_CALLBACK_INVOKER, Object.class); 4.71 + } 4.72 + 4.73 + private static MethodHandle getFILTER_CALLBACK_INVOKER() { 4.74 + return createIteratorCallbackInvoker(FILTER_CALLBACK_INVOKER, boolean.class); 4.75 + } 4.76 + 4.77 + private static MethodHandle getREDUCE_CALLBACK_INVOKER() { 4.78 + return Global.instance().getDynamicInvoker(REDUCE_CALLBACK_INVOKER, 4.79 + new Callable<MethodHandle>() { 4.80 + @Override 4.81 + public MethodHandle call() { 4.82 + return Bootstrap.createDynamicInvoker("dyn:call", Object.class, Object.class, 4.83 + Undefined.class, Object.class, Object.class, long.class, Object.class); 4.84 + } 4.85 + }); 4.86 + } 4.87 + 4.88 + private static MethodHandle getCALL_CMP() { 4.89 + return Global.instance().getDynamicInvoker(CALL_CMP, 4.90 + new Callable<MethodHandle>() { 4.91 + @Override 4.92 + public MethodHandle call() { 4.93 + return Bootstrap.createDynamicInvoker("dyn:call", double.class, 4.94 + ScriptFunction.class, Object.class, Object.class, Object.class); 4.95 + } 4.96 + }); 4.97 + } 4.98 + 4.99 + private static InvokeByName getTO_LOCALE_STRING() { 4.100 + return Global.instance().getInvokeByName(TO_LOCALE_STRING, 4.101 + new Callable<InvokeByName>() { 4.102 + @Override 4.103 + public InvokeByName call() { 4.104 + return new InvokeByName("toLocaleString", ScriptObject.class, String.class); 4.105 + } 4.106 + }); 4.107 + } 4.108 4.109 // initialized by nasgen 4.110 private static PropertyMap $nasgenmap$; 4.111 @@ -357,11 +426,12 @@ 4.112 public static Object toString(final Object self) { 4.113 final Object obj = Global.toObject(self); 4.114 if (obj instanceof ScriptObject) { 4.115 + final InvokeByName joinInvoker = getJOIN(); 4.116 final ScriptObject sobj = (ScriptObject)obj; 4.117 try { 4.118 - final Object join = JOIN.getGetter().invokeExact(sobj); 4.119 + final Object join = joinInvoker.getGetter().invokeExact(sobj); 4.120 if (Bootstrap.isCallable(join)) { 4.121 - return JOIN.getInvoker().invokeExact(join, sobj); 4.122 + return joinInvoker.getInvoker().invokeExact(join, sobj); 4.123 } 4.124 } catch (final RuntimeException | Error e) { 4.125 throw e; 4.126 @@ -393,11 +463,12 @@ 4.127 4.128 try { 4.129 if (val instanceof ScriptObject) { 4.130 + final InvokeByName localeInvoker = getTO_LOCALE_STRING(); 4.131 final ScriptObject sobj = (ScriptObject)val; 4.132 - final Object toLocaleString = TO_LOCALE_STRING.getGetter().invokeExact(sobj); 4.133 + final Object toLocaleString = localeInvoker.getGetter().invokeExact(sobj); 4.134 4.135 if (Bootstrap.isCallable(toLocaleString)) { 4.136 - sb.append((String)TO_LOCALE_STRING.getInvoker().invokeExact(toLocaleString, sobj)); 4.137 + sb.append((String)localeInvoker.getInvoker().invokeExact(toLocaleString, sobj)); 4.138 } else { 4.139 throw typeError("not.a.function", "toLocaleString"); 4.140 } 4.141 @@ -814,6 +885,7 @@ 4.142 final Object cmpThis = cmp == null || cmp.isStrict() ? ScriptRuntime.UNDEFINED : Global.instance(); 4.143 4.144 Collections.sort(list, new Comparator<Object>() { 4.145 + private final MethodHandle call_cmp = getCALL_CMP(); 4.146 @Override 4.147 public int compare(final Object x, final Object y) { 4.148 if (x == ScriptRuntime.UNDEFINED && y == ScriptRuntime.UNDEFINED) { 4.149 @@ -826,7 +898,7 @@ 4.150 4.151 if (cmp != null) { 4.152 try { 4.153 - return (int)Math.signum((double)CALL_CMP.invokeExact(cmp, cmpThis, x, y)); 4.154 + return (int)Math.signum((double)call_cmp.invokeExact(cmp, cmpThis, x, y)); 4.155 } catch (final RuntimeException | Error e) { 4.156 throw e; 4.157 } catch (final Throwable t) { 4.158 @@ -1103,9 +1175,11 @@ 4.159 4.160 private static boolean applyEvery(final Object self, final Object callbackfn, final Object thisArg) { 4.161 return new IteratorAction<Boolean>(Global.toObject(self), callbackfn, thisArg, true) { 4.162 + private final MethodHandle everyInvoker = getEVERY_CALLBACK_INVOKER(); 4.163 + 4.164 @Override 4.165 protected boolean forEach(final Object val, final long i) throws Throwable { 4.166 - return (result = (boolean)EVERY_CALLBACK_INVOKER.invokeExact(callbackfn, thisArg, val, i, self)); 4.167 + return (result = (boolean)everyInvoker.invokeExact(callbackfn, thisArg, val, i, self)); 4.168 } 4.169 }.apply(); 4.170 } 4.171 @@ -1121,9 +1195,11 @@ 4.172 @Function(attributes = Attribute.NOT_ENUMERABLE, arity = 1) 4.173 public static Object some(final Object self, final Object callbackfn, final Object thisArg) { 4.174 return new IteratorAction<Boolean>(Global.toObject(self), callbackfn, thisArg, false) { 4.175 + private final MethodHandle someInvoker = getSOME_CALLBACK_INVOKER(); 4.176 + 4.177 @Override 4.178 protected boolean forEach(final Object val, final long i) throws Throwable { 4.179 - return !(result = (boolean)SOME_CALLBACK_INVOKER.invokeExact(callbackfn, thisArg, val, i, self)); 4.180 + return !(result = (boolean)someInvoker.invokeExact(callbackfn, thisArg, val, i, self)); 4.181 } 4.182 }.apply(); 4.183 } 4.184 @@ -1139,9 +1215,11 @@ 4.185 @Function(attributes = Attribute.NOT_ENUMERABLE, arity = 1) 4.186 public static Object forEach(final Object self, final Object callbackfn, final Object thisArg) { 4.187 return new IteratorAction<Object>(Global.toObject(self), callbackfn, thisArg, ScriptRuntime.UNDEFINED) { 4.188 + private final MethodHandle forEachInvoker = getFOREACH_CALLBACK_INVOKER(); 4.189 + 4.190 @Override 4.191 protected boolean forEach(final Object val, final long i) throws Throwable { 4.192 - FOREACH_CALLBACK_INVOKER.invokeExact(callbackfn, thisArg, val, i, self); 4.193 + forEachInvoker.invokeExact(callbackfn, thisArg, val, i, self); 4.194 return true; 4.195 } 4.196 }.apply(); 4.197 @@ -1158,9 +1236,11 @@ 4.198 @Function(attributes = Attribute.NOT_ENUMERABLE, arity = 1) 4.199 public static Object map(final Object self, final Object callbackfn, final Object thisArg) { 4.200 return new IteratorAction<NativeArray>(Global.toObject(self), callbackfn, thisArg, null) { 4.201 + private final MethodHandle mapInvoker = getMAP_CALLBACK_INVOKER(); 4.202 + 4.203 @Override 4.204 protected boolean forEach(final Object val, final long i) throws Throwable { 4.205 - final Object r = MAP_CALLBACK_INVOKER.invokeExact(callbackfn, thisArg, val, i, self); 4.206 + final Object r = mapInvoker.invokeExact(callbackfn, thisArg, val, i, self); 4.207 result.defineOwnProperty(ArrayIndex.getArrayIndex(index), r); 4.208 return true; 4.209 } 4.210 @@ -1186,10 +1266,11 @@ 4.211 public static Object filter(final Object self, final Object callbackfn, final Object thisArg) { 4.212 return new IteratorAction<NativeArray>(Global.toObject(self), callbackfn, thisArg, new NativeArray()) { 4.213 private long to = 0; 4.214 + private final MethodHandle filterInvoker = getFILTER_CALLBACK_INVOKER(); 4.215 4.216 @Override 4.217 protected boolean forEach(final Object val, final long i) throws Throwable { 4.218 - if ((boolean)FILTER_CALLBACK_INVOKER.invokeExact(callbackfn, thisArg, val, i, self)) { 4.219 + if ((boolean)filterInvoker.invokeExact(callbackfn, thisArg, val, i, self)) { 4.220 result.defineOwnProperty(ArrayIndex.getArrayIndex(to++), val); 4.221 } 4.222 return true; 4.223 @@ -1217,10 +1298,12 @@ 4.224 4.225 //if initial value is ScriptRuntime.UNDEFINED - step forward once. 4.226 return new IteratorAction<Object>(Global.toObject(self), callbackfn, ScriptRuntime.UNDEFINED, initialValue, iter) { 4.227 + private final MethodHandle reduceInvoker = getREDUCE_CALLBACK_INVOKER(); 4.228 + 4.229 @Override 4.230 protected boolean forEach(final Object val, final long i) throws Throwable { 4.231 // TODO: why can't I declare the second arg as Undefined.class? 4.232 - result = REDUCE_CALLBACK_INVOKER.invokeExact(callbackfn, ScriptRuntime.UNDEFINED, result, val, i, self); 4.233 + result = reduceInvoker.invokeExact(callbackfn, ScriptRuntime.UNDEFINED, result, val, i, self); 4.234 return true; 4.235 } 4.236 }.apply(); 4.237 @@ -1273,10 +1356,4 @@ 4.238 4.239 return false; 4.240 } 4.241 - 4.242 - private static MethodHandle createIteratorCallbackInvoker(final Class<?> rtype) { 4.243 - return Bootstrap.createDynamicInvoker("dyn:call", rtype, Object.class, Object.class, Object.class, 4.244 - long.class, Object.class); 4.245 - 4.246 - } 4.247 }
5.1 --- a/src/jdk/nashorn/internal/objects/NativeDate.java Wed Aug 07 16:38:44 2013 +0200 5.2 +++ b/src/jdk/nashorn/internal/objects/NativeDate.java Thu Aug 08 16:38:32 2013 +0530 5.3 @@ -33,6 +33,7 @@ 5.4 5.5 import java.util.Locale; 5.6 import java.util.TimeZone; 5.7 +import java.util.concurrent.Callable; 5.8 import jdk.nashorn.internal.objects.annotations.Attribute; 5.9 import jdk.nashorn.internal.objects.annotations.Constructor; 5.10 import jdk.nashorn.internal.objects.annotations.Function; 5.11 @@ -95,8 +96,17 @@ 5.12 "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" 5.13 }; 5.14 5.15 - private static final InvokeByName TO_ISO_STRING = new InvokeByName("toISOString", ScriptObject.class, Object.class, 5.16 - Object.class); 5.17 + private static final Object TO_ISO_STRING = new Object(); 5.18 + 5.19 + private static InvokeByName getTO_ISO_STRING() { 5.20 + return Global.instance().getInvokeByName(TO_ISO_STRING, 5.21 + new Callable<InvokeByName>() { 5.22 + @Override 5.23 + public InvokeByName call() { 5.24 + return new InvokeByName("toISOString", ScriptObject.class, Object.class, Object.class); 5.25 + } 5.26 + }); 5.27 + } 5.28 5.29 private double time; 5.30 private final TimeZone timezone; 5.31 @@ -861,9 +871,10 @@ 5.32 } 5.33 5.34 try { 5.35 - final Object func = TO_ISO_STRING.getGetter().invokeExact(sobj); 5.36 + final InvokeByName toIsoString = getTO_ISO_STRING(); 5.37 + final Object func = toIsoString.getGetter().invokeExact(sobj); 5.38 if (Bootstrap.isCallable(func)) { 5.39 - return TO_ISO_STRING.getInvoker().invokeExact(func, sobj, key); 5.40 + return toIsoString.getInvoker().invokeExact(func, sobj, key); 5.41 } 5.42 throw typeError("not.a.function", ScriptRuntime.safeToString(func)); 5.43 } catch (final RuntimeException | Error e) {
6.1 --- a/src/jdk/nashorn/internal/objects/NativeJSON.java Wed Aug 07 16:38:44 2013 +0200 6.2 +++ b/src/jdk/nashorn/internal/objects/NativeJSON.java Thu Aug 08 16:38:32 2013 +0530 6.3 @@ -35,6 +35,7 @@ 6.4 import java.util.Iterator; 6.5 import java.util.List; 6.6 import java.util.Map; 6.7 +import java.util.concurrent.Callable; 6.8 import jdk.nashorn.internal.objects.annotations.Attribute; 6.9 import jdk.nashorn.internal.objects.annotations.Function; 6.10 import jdk.nashorn.internal.objects.annotations.ScriptClass; 6.11 @@ -55,9 +56,31 @@ 6.12 */ 6.13 @ScriptClass("JSON") 6.14 public final class NativeJSON extends ScriptObject { 6.15 - private static final InvokeByName TO_JSON = new InvokeByName("toJSON", ScriptObject.class, Object.class, Object.class); 6.16 - private static final MethodHandle REPLACER_INVOKER = Bootstrap.createDynamicInvoker("dyn:call", Object.class, 6.17 - ScriptFunction.class, ScriptObject.class, Object.class, Object.class); 6.18 + private static final Object TO_JSON = new Object(); 6.19 + 6.20 + private static InvokeByName getTO_JSON() { 6.21 + return Global.instance().getInvokeByName(TO_JSON, 6.22 + new Callable<InvokeByName>() { 6.23 + @Override 6.24 + public InvokeByName call() { 6.25 + return new InvokeByName("toJSON", ScriptObject.class, Object.class, Object.class); 6.26 + } 6.27 + }); 6.28 + } 6.29 + 6.30 + 6.31 + private static final Object REPLACER_INVOKER = new Object(); 6.32 + 6.33 + private static MethodHandle getREPLACER_INVOKER() { 6.34 + return Global.instance().getDynamicInvoker(REPLACER_INVOKER, 6.35 + new Callable<MethodHandle>() { 6.36 + @Override 6.37 + public MethodHandle call() { 6.38 + return Bootstrap.createDynamicInvoker("dyn:call", Object.class, 6.39 + ScriptFunction.class, ScriptObject.class, Object.class, Object.class); 6.40 + } 6.41 + }); 6.42 + } 6.43 6.44 // initialized by nasgen 6.45 @SuppressWarnings("unused") 6.46 @@ -187,15 +210,16 @@ 6.47 6.48 try { 6.49 if (value instanceof ScriptObject) { 6.50 + final InvokeByName toJSONInvoker = getTO_JSON(); 6.51 final ScriptObject svalue = (ScriptObject)value; 6.52 - final Object toJSON = TO_JSON.getGetter().invokeExact(svalue); 6.53 + final Object toJSON = toJSONInvoker.getGetter().invokeExact(svalue); 6.54 if (Bootstrap.isCallable(toJSON)) { 6.55 - value = TO_JSON.getInvoker().invokeExact(toJSON, svalue, key); 6.56 + value = toJSONInvoker.getInvoker().invokeExact(toJSON, svalue, key); 6.57 } 6.58 } 6.59 6.60 if (state.replacerFunction != null) { 6.61 - value = REPLACER_INVOKER.invokeExact(state.replacerFunction, holder, key, value); 6.62 + value = getREPLACER_INVOKER().invokeExact(state.replacerFunction, holder, key, value); 6.63 } 6.64 } catch(Error|RuntimeException t) { 6.65 throw t;
7.1 --- a/src/jdk/nashorn/internal/objects/NativeObject.java Wed Aug 07 16:38:44 2013 +0200 7.2 +++ b/src/jdk/nashorn/internal/objects/NativeObject.java Thu Aug 08 16:38:32 2013 +0530 7.3 @@ -36,6 +36,7 @@ 7.4 import java.util.HashSet; 7.5 import java.util.List; 7.6 import java.util.Set; 7.7 +import java.util.concurrent.Callable; 7.8 import jdk.internal.dynalink.beans.BeansLinker; 7.9 import jdk.internal.dynalink.beans.StaticClass; 7.10 import jdk.internal.dynalink.linker.GuardedInvocation; 7.11 @@ -70,7 +71,18 @@ 7.12 */ 7.13 @ScriptClass("Object") 7.14 public final class NativeObject { 7.15 - private static final InvokeByName TO_STRING = new InvokeByName("toString", ScriptObject.class); 7.16 + private static final Object TO_STRING = new Object(); 7.17 + 7.18 + private static InvokeByName getTO_STRING() { 7.19 + return Global.instance().getInvokeByName(TO_STRING, 7.20 + new Callable<InvokeByName>() { 7.21 + @Override 7.22 + public InvokeByName call() { 7.23 + return new InvokeByName("toString", ScriptObject.class); 7.24 + } 7.25 + }); 7.26 + } 7.27 + 7.28 private static final MethodType MIRROR_GETTER_TYPE = MethodType.methodType(Object.class, ScriptObjectMirror.class); 7.29 private static final MethodType MIRROR_SETTER_TYPE = MethodType.methodType(Object.class, ScriptObjectMirror.class, Object.class); 7.30 7.31 @@ -402,12 +414,13 @@ 7.32 public static Object toLocaleString(final Object self) { 7.33 final Object obj = JSType.toScriptObject(self); 7.34 if (obj instanceof ScriptObject) { 7.35 + final InvokeByName toStringInvoker = getTO_STRING(); 7.36 final ScriptObject sobj = (ScriptObject)self; 7.37 try { 7.38 - final Object toString = TO_STRING.getGetter().invokeExact(sobj); 7.39 + final Object toString = toStringInvoker.getGetter().invokeExact(sobj); 7.40 7.41 if (Bootstrap.isCallable(toString)) { 7.42 - return TO_STRING.getInvoker().invokeExact(toString, sobj); 7.43 + return toStringInvoker.getInvoker().invokeExact(toString, sobj); 7.44 } 7.45 } catch (final RuntimeException | Error e) { 7.46 throw e;
8.1 --- a/src/jdk/nashorn/internal/runtime/GlobalObject.java Wed Aug 07 16:38:44 2013 +0200 8.2 +++ b/src/jdk/nashorn/internal/runtime/GlobalObject.java Thu Aug 08 16:38:32 2013 +0530 8.3 @@ -26,8 +26,10 @@ 8.4 package jdk.nashorn.internal.runtime; 8.5 8.6 import java.lang.invoke.MethodHandle; 8.7 +import java.util.concurrent.Callable; 8.8 import jdk.internal.dynalink.linker.GuardedInvocation; 8.9 import jdk.internal.dynalink.linker.LinkRequest; 8.10 +import jdk.nashorn.internal.runtime.linker.InvokeByName; 8.11 8.12 /** 8.13 * Runtime interface to the global scope objects. 8.14 @@ -210,4 +212,20 @@ 8.15 * @param clazz compiled Class object for the source 8.16 */ 8.17 public void cacheClass(Source source, Class<?> clazz); 8.18 + 8.19 + /** 8.20 + * Get cached InvokeByName object for the given key 8.21 + * @param key key to be associated with InvokeByName object 8.22 + * @param creator if InvokeByName is absent 'creator' is called to make one (lazy init) 8.23 + * @return InvokeByName object associated with the key. 8.24 + */ 8.25 + public InvokeByName getInvokeByName(final Object key, final Callable<InvokeByName> creator); 8.26 + 8.27 + /** 8.28 + * Get cached dynamic method handle for the given key 8.29 + * @param key key to be associated with dynamic method handle 8.30 + * @param creator if method handle is absent 'creator' is called to make one (lazy init) 8.31 + * @return dynamic method handle associated with the key. 8.32 + */ 8.33 + public MethodHandle getDynamicInvoker(final Object key, final Callable<MethodHandle> creator); 8.34 }
9.1 --- a/src/jdk/nashorn/internal/runtime/JSONFunctions.java Wed Aug 07 16:38:44 2013 +0200 9.2 +++ b/src/jdk/nashorn/internal/runtime/JSONFunctions.java Thu Aug 08 16:38:32 2013 +0530 9.3 @@ -27,6 +27,7 @@ 9.4 9.5 import java.lang.invoke.MethodHandle; 9.6 import java.util.Iterator; 9.7 +import java.util.concurrent.Callable; 9.8 import jdk.nashorn.internal.ir.LiteralNode; 9.9 import jdk.nashorn.internal.ir.Node; 9.10 import jdk.nashorn.internal.ir.ObjectNode; 9.11 @@ -42,8 +43,19 @@ 9.12 */ 9.13 public final class JSONFunctions { 9.14 private JSONFunctions() {} 9.15 - private static final MethodHandle REVIVER_INVOKER = Bootstrap.createDynamicInvoker("dyn:call", Object.class, 9.16 - ScriptFunction.class, ScriptObject.class, String.class, Object.class); 9.17 + 9.18 + private static final Object REVIVER_INVOKER = new Object(); 9.19 + 9.20 + private static MethodHandle getREVIVER_INVOKER() { 9.21 + return ((GlobalObject)Context.getGlobal()).getDynamicInvoker(REVIVER_INVOKER, 9.22 + new Callable<MethodHandle>() { 9.23 + @Override 9.24 + public MethodHandle call() { 9.25 + return Bootstrap.createDynamicInvoker("dyn:call", Object.class, 9.26 + ScriptFunction.class, ScriptObject.class, String.class, Object.class); 9.27 + } 9.28 + }); 9.29 + } 9.30 9.31 /** 9.32 * Returns JSON-compatible quoted version of the given string. 9.33 @@ -117,7 +129,7 @@ 9.34 9.35 try { 9.36 // Object.class, ScriptFunction.class, ScriptObject.class, String.class, Object.class); 9.37 - return REVIVER_INVOKER.invokeExact(reviver, holder, JSType.toString(name), val); 9.38 + return getREVIVER_INVOKER().invokeExact(reviver, holder, JSType.toString(name), val); 9.39 } catch(Error|RuntimeException t) { 9.40 throw t; 9.41 } catch(final Throwable t) {
10.1 --- a/src/jdk/nashorn/internal/runtime/ListAdapter.java Wed Aug 07 16:38:44 2013 +0200 10.2 +++ b/src/jdk/nashorn/internal/runtime/ListAdapter.java Thu Aug 08 16:38:32 2013 +0530 10.3 @@ -31,6 +31,7 @@ 10.4 import java.util.ListIterator; 10.5 import java.util.NoSuchElementException; 10.6 import java.util.RandomAccess; 10.7 +import java.util.concurrent.Callable; 10.8 import jdk.nashorn.internal.runtime.linker.Bootstrap; 10.9 import jdk.nashorn.internal.runtime.linker.InvokeByName; 10.10 10.11 @@ -49,16 +50,73 @@ 10.12 */ 10.13 public final class ListAdapter extends AbstractList<Object> implements RandomAccess, Deque<Object> { 10.14 // These add to the back and front of the list 10.15 - private static final InvokeByName PUSH = new InvokeByName("push", ScriptObject.class, void.class, Object.class); 10.16 - private static final InvokeByName UNSHIFT = new InvokeByName("unshift", ScriptObject.class, void.class, Object.class); 10.17 + private static final Object PUSH = new Object(); 10.18 + private static InvokeByName getPUSH() { 10.19 + return ((GlobalObject)Context.getGlobal()).getInvokeByName(PUSH, 10.20 + new Callable<InvokeByName>() { 10.21 + @Override 10.22 + public InvokeByName call() { 10.23 + return new InvokeByName("push", ScriptObject.class, void.class, Object.class); 10.24 + } 10.25 + }); 10.26 + } 10.27 + 10.28 + private static final Object UNSHIFT = new Object(); 10.29 + private static InvokeByName getUNSHIFT() { 10.30 + return ((GlobalObject)Context.getGlobal()).getInvokeByName(UNSHIFT, 10.31 + new Callable<InvokeByName>() { 10.32 + @Override 10.33 + public InvokeByName call() { 10.34 + return new InvokeByName("unshift", ScriptObject.class, void.class, Object.class); 10.35 + } 10.36 + }); 10.37 + } 10.38 10.39 // These remove from the back and front of the list 10.40 - private static final InvokeByName POP = new InvokeByName("pop", ScriptObject.class, Object.class); 10.41 - private static final InvokeByName SHIFT = new InvokeByName("shift", ScriptObject.class, Object.class); 10.42 + private static final Object POP = new Object(); 10.43 + private static InvokeByName getPOP() { 10.44 + return ((GlobalObject)Context.getGlobal()).getInvokeByName(POP, 10.45 + new Callable<InvokeByName>() { 10.46 + @Override 10.47 + public InvokeByName call() { 10.48 + return new InvokeByName("pop", ScriptObject.class, Object.class); 10.49 + } 10.50 + }); 10.51 + } 10.52 + 10.53 + private static final Object SHIFT = new Object(); 10.54 + private static InvokeByName getSHIFT() { 10.55 + return ((GlobalObject)Context.getGlobal()).getInvokeByName(SHIFT, 10.56 + new Callable<InvokeByName>() { 10.57 + @Override 10.58 + public InvokeByName call() { 10.59 + return new InvokeByName("shift", ScriptObject.class, Object.class); 10.60 + } 10.61 + }); 10.62 + } 10.63 10.64 // These insert and remove in the middle of the list 10.65 - private static final InvokeByName SPLICE_ADD = new InvokeByName("splice", ScriptObject.class, void.class, int.class, int.class, Object.class); 10.66 - private static final InvokeByName SPLICE_REMOVE = new InvokeByName("splice", ScriptObject.class, void.class, int.class, int.class); 10.67 + private static final Object SPLICE_ADD = new Object(); 10.68 + private static InvokeByName getSPLICE_ADD() { 10.69 + return ((GlobalObject)Context.getGlobal()).getInvokeByName(SPLICE_ADD, 10.70 + new Callable<InvokeByName>() { 10.71 + @Override 10.72 + public InvokeByName call() { 10.73 + return new InvokeByName("splice", ScriptObject.class, void.class, int.class, int.class, Object.class); 10.74 + } 10.75 + }); 10.76 + } 10.77 + 10.78 + private static final Object SPLICE_REMOVE = new Object(); 10.79 + private static InvokeByName getSPLICE_REMOVE() { 10.80 + return ((GlobalObject)Context.getGlobal()).getInvokeByName(SPLICE_REMOVE, 10.81 + new Callable<InvokeByName>() { 10.82 + @Override 10.83 + public InvokeByName call() { 10.84 + return new InvokeByName("splice", ScriptObject.class, void.class, int.class, int.class); 10.85 + } 10.86 + }); 10.87 + } 10.88 10.89 private final ScriptObject obj; 10.90 10.91 @@ -109,9 +167,10 @@ 10.92 @Override 10.93 public void addFirst(Object e) { 10.94 try { 10.95 - final Object fn = UNSHIFT.getGetter().invokeExact(obj); 10.96 - checkFunction(fn, UNSHIFT); 10.97 - UNSHIFT.getInvoker().invokeExact(fn, obj, e); 10.98 + final InvokeByName unshiftInvoker = getUNSHIFT(); 10.99 + final Object fn = unshiftInvoker.getGetter().invokeExact(obj); 10.100 + checkFunction(fn, unshiftInvoker); 10.101 + unshiftInvoker.getInvoker().invokeExact(fn, obj, e); 10.102 } catch(RuntimeException | Error ex) { 10.103 throw ex; 10.104 } catch(Throwable t) { 10.105 @@ -122,9 +181,10 @@ 10.106 @Override 10.107 public void addLast(Object e) { 10.108 try { 10.109 - final Object fn = PUSH.getGetter().invokeExact(obj); 10.110 - checkFunction(fn, PUSH); 10.111 - PUSH.getInvoker().invokeExact(fn, obj, e); 10.112 + final InvokeByName pushInvoker = getPUSH(); 10.113 + final Object fn = pushInvoker.getGetter().invokeExact(obj); 10.114 + checkFunction(fn, pushInvoker); 10.115 + pushInvoker.getInvoker().invokeExact(fn, obj, e); 10.116 } catch(RuntimeException | Error ex) { 10.117 throw ex; 10.118 } catch(Throwable t) { 10.119 @@ -142,9 +202,10 @@ 10.120 } else { 10.121 final int size = size(); 10.122 if(index < size) { 10.123 - final Object fn = SPLICE_ADD.getGetter().invokeExact(obj); 10.124 - checkFunction(fn, SPLICE_ADD); 10.125 - SPLICE_ADD.getInvoker().invokeExact(fn, obj, index, 0, e); 10.126 + final InvokeByName spliceAddInvoker = getSPLICE_ADD(); 10.127 + final Object fn = spliceAddInvoker.getGetter().invokeExact(obj); 10.128 + checkFunction(fn, spliceAddInvoker); 10.129 + spliceAddInvoker.getInvoker().invokeExact(fn, obj, index, 0, e); 10.130 } else if(index == size) { 10.131 addLast(e); 10.132 } else { 10.133 @@ -234,9 +295,10 @@ 10.134 10.135 private Object invokeShift() { 10.136 try { 10.137 - final Object fn = SHIFT.getGetter().invokeExact(obj); 10.138 - checkFunction(fn, SHIFT); 10.139 - return SHIFT.getInvoker().invokeExact(fn, obj); 10.140 + final InvokeByName shiftInvoker = getSHIFT(); 10.141 + final Object fn = shiftInvoker.getGetter().invokeExact(obj); 10.142 + checkFunction(fn, shiftInvoker); 10.143 + return shiftInvoker.getInvoker().invokeExact(fn, obj); 10.144 } catch(RuntimeException | Error ex) { 10.145 throw ex; 10.146 } catch(Throwable t) { 10.147 @@ -246,9 +308,10 @@ 10.148 10.149 private Object invokePop() { 10.150 try { 10.151 - final Object fn = POP.getGetter().invokeExact(obj); 10.152 - checkFunction(fn, POP); 10.153 - return POP.getInvoker().invokeExact(fn, obj); 10.154 + final InvokeByName popInvoker = getPOP(); 10.155 + final Object fn = popInvoker.getGetter().invokeExact(obj); 10.156 + checkFunction(fn, popInvoker); 10.157 + return popInvoker.getInvoker().invokeExact(fn, obj); 10.158 } catch(RuntimeException | Error ex) { 10.159 throw ex; 10.160 } catch(Throwable t) { 10.161 @@ -263,9 +326,10 @@ 10.162 10.163 private void invokeSpliceRemove(int fromIndex, int count) { 10.164 try { 10.165 - final Object fn = SPLICE_REMOVE.getGetter().invokeExact(obj); 10.166 - checkFunction(fn, SPLICE_REMOVE); 10.167 - SPLICE_REMOVE.getInvoker().invokeExact(fn, obj, fromIndex, count); 10.168 + final InvokeByName spliceRemoveInvoker = getSPLICE_REMOVE(); 10.169 + final Object fn = spliceRemoveInvoker.getGetter().invokeExact(obj); 10.170 + checkFunction(fn, spliceRemoveInvoker); 10.171 + spliceRemoveInvoker.getInvoker().invokeExact(fn, obj, fromIndex, count); 10.172 } catch(RuntimeException | Error ex) { 10.173 throw ex; 10.174 } catch(Throwable t) {
11.1 --- a/src/jdk/nashorn/internal/runtime/RecompilableScriptFunctionData.java Wed Aug 07 16:38:44 2013 +0200 11.2 +++ b/src/jdk/nashorn/internal/runtime/RecompilableScriptFunctionData.java Thu Aug 08 16:38:32 2013 +0530 11.3 @@ -52,13 +52,19 @@ 11.4 public final class RecompilableScriptFunctionData extends ScriptFunctionData { 11.5 11.6 /** FunctionNode with the code for this ScriptFunction */ 11.7 - private FunctionNode functionNode; 11.8 + private volatile FunctionNode functionNode; 11.9 + 11.10 + /** Source from which FunctionNode was parsed. */ 11.11 + private final Source source; 11.12 + 11.13 + /** Token of this function within the source. */ 11.14 + private final long token; 11.15 11.16 /** Allocator map from makeMap() */ 11.17 private final PropertyMap allocatorMap; 11.18 11.19 /** Code installer used for all further recompilation/specialization of this ScriptFunction */ 11.20 - private final CodeInstaller<ScriptEnvironment> installer; 11.21 + private volatile CodeInstaller<ScriptEnvironment> installer; 11.22 11.23 /** Name of class where allocator function resides */ 11.24 private final String allocatorClassName; 11.25 @@ -103,6 +109,8 @@ 11.26 true); 11.27 11.28 this.functionNode = functionNode; 11.29 + this.source = functionNode.getSource(); 11.30 + this.token = tokenFor(functionNode); 11.31 this.installer = installer; 11.32 this.allocatorClassName = allocatorClassName; 11.33 this.allocatorMap = allocatorMap; 11.34 @@ -110,9 +118,6 @@ 11.35 11.36 @Override 11.37 String toSource() { 11.38 - final Source source = functionNode.getSource(); 11.39 - final long token = tokenFor(functionNode); 11.40 - 11.41 if (source != null && token != 0) { 11.42 return source.getString(Token.descPosition(token), Token.descLength(token)); 11.43 } 11.44 @@ -123,8 +128,6 @@ 11.45 @Override 11.46 public String toString() { 11.47 final StringBuilder sb = new StringBuilder(); 11.48 - final Source source = functionNode.getSource(); 11.49 - final long token = tokenFor(functionNode); 11.50 11.51 if (source != null) { 11.52 sb.append(source.getName()) 11.53 @@ -190,6 +193,12 @@ 11.54 11.55 // code exists - look it up and add it into the automatically sorted invoker list 11.56 addCode(functionNode); 11.57 + 11.58 + if (! functionNode.canSpecialize()) { 11.59 + // allow GC to claim IR stuff that is not needed anymore 11.60 + functionNode = null; 11.61 + installer = null; 11.62 + } 11.63 } 11.64 11.65 private MethodHandle addCode(final FunctionNode fn) { 11.66 @@ -325,7 +334,7 @@ 11.67 * footprint too large to store a parse snapshot, or if it is meaningless 11.68 * to do so, such as e.g. for runScript 11.69 */ 11.70 - if (!functionNode.canSpecialize()) { 11.71 + if (functionNode == null || !functionNode.canSpecialize()) { 11.72 return mh; 11.73 } 11.74
12.1 --- a/src/jdk/nashorn/internal/runtime/ScriptFunction.java Wed Aug 07 16:38:44 2013 +0200 12.2 +++ b/src/jdk/nashorn/internal/runtime/ScriptFunction.java Thu Aug 08 16:38:32 2013 +0530 12.3 @@ -496,32 +496,24 @@ 12.4 MethodHandle boundHandle; 12.5 MethodHandle guard = null; 12.6 12.7 + final boolean scopeCall = NashornCallSiteDescriptor.isScope(desc); 12.8 + 12.9 if (data.needsCallee()) { 12.10 final MethodHandle callHandle = getBestInvoker(type, request.getArguments()); 12.11 - if (NashornCallSiteDescriptor.isScope(desc)) { 12.12 + if (scopeCall) { 12.13 // Make a handle that drops the passed "this" argument and substitutes either Global or Undefined 12.14 // (callee, this, args...) => (callee, args...) 12.15 boundHandle = MH.insertArguments(callHandle, 1, needsWrappedThis() ? Context.getGlobalTrusted() : ScriptRuntime.UNDEFINED); 12.16 // (callee, args...) => (callee, [this], args...) 12.17 boundHandle = MH.dropArguments(boundHandle, 1, Object.class); 12.18 + 12.19 } else { 12.20 // It's already (callee, this, args...), just what we need 12.21 boundHandle = callHandle; 12.22 - 12.23 - // For non-strict functions, check whether this-object is primitive type. 12.24 - // If so add a to-object-wrapper argument filter. 12.25 - // Else install a guard that will trigger a relink when the argument becomes primitive. 12.26 - if (needsWrappedThis()) { 12.27 - if (ScriptFunctionData.isPrimitiveThis(request.getArguments()[1])) { 12.28 - boundHandle = MH.filterArguments(boundHandle, 1, WRAPFILTER); 12.29 - } else { 12.30 - guard = getNonStrictFunctionGuard(this); 12.31 - } 12.32 - } 12.33 } 12.34 } else { 12.35 final MethodHandle callHandle = getBestInvoker(type.dropParameterTypes(0, 1), request.getArguments()); 12.36 - if (NashornCallSiteDescriptor.isScope(desc)) { 12.37 + if (scopeCall) { 12.38 // Make a handle that drops the passed "this" argument and substitutes either Global or Undefined 12.39 // (this, args...) => (args...) 12.40 boundHandle = MH.bindTo(callHandle, needsWrappedThis() ? Context.getGlobalTrusted() : ScriptRuntime.UNDEFINED); 12.41 @@ -533,6 +525,17 @@ 12.42 } 12.43 } 12.44 12.45 + // For non-strict functions, check whether this-object is primitive type. 12.46 + // If so add a to-object-wrapper argument filter. 12.47 + // Else install a guard that will trigger a relink when the argument becomes primitive. 12.48 + if (!scopeCall && needsWrappedThis()) { 12.49 + if (ScriptFunctionData.isPrimitiveThis(request.getArguments()[1])) { 12.50 + boundHandle = MH.filterArguments(boundHandle, 1, WRAPFILTER); 12.51 + } else { 12.52 + guard = getNonStrictFunctionGuard(this); 12.53 + } 12.54 + } 12.55 + 12.56 boundHandle = pairArguments(boundHandle, type); 12.57 12.58 return new GuardedInvocation(boundHandle, guard == null ? getFunctionGuard(this) : guard);
13.1 --- a/src/jdk/nashorn/internal/runtime/UserAccessorProperty.java Wed Aug 07 16:38:44 2013 +0200 13.2 +++ b/src/jdk/nashorn/internal/runtime/UserAccessorProperty.java Thu Aug 08 16:38:32 2013 +0530 13.3 @@ -27,6 +27,7 @@ 13.4 13.5 import java.lang.invoke.MethodHandle; 13.6 import java.lang.invoke.MethodHandles; 13.7 +import java.util.concurrent.Callable; 13.8 13.9 import jdk.nashorn.internal.codegen.CompilerConstants; 13.10 import jdk.nashorn.internal.lookup.Lookup; 13.11 @@ -68,12 +69,32 @@ 13.12 "userAccessorSetter", void.class, ScriptObject.class, int.class, String.class, Object.class, Object.class); 13.13 13.14 /** Dynamic invoker for getter */ 13.15 - private static final MethodHandle INVOKE_UA_GETTER = Bootstrap.createDynamicInvoker("dyn:call", Object.class, 13.16 - Object.class, Object.class); 13.17 + private static final Object INVOKE_UA_GETTER = new Object(); 13.18 + 13.19 + private static MethodHandle getINVOKE_UA_GETTER() { 13.20 + 13.21 + return ((GlobalObject)Context.getGlobal()).getDynamicInvoker(INVOKE_UA_GETTER, 13.22 + new Callable<MethodHandle>() { 13.23 + @Override 13.24 + public MethodHandle call() { 13.25 + return Bootstrap.createDynamicInvoker("dyn:call", Object.class, 13.26 + Object.class, Object.class); 13.27 + } 13.28 + }); 13.29 + } 13.30 13.31 /** Dynamic invoker for setter */ 13.32 - private static final MethodHandle INVOKE_UA_SETTER = Bootstrap.createDynamicInvoker("dyn:call", void.class, 13.33 - Object.class, Object.class, Object.class); 13.34 + private static Object INVOKE_UA_SETTER = new Object(); 13.35 + private static MethodHandle getINVOKE_UA_SETTER() { 13.36 + return ((GlobalObject)Context.getGlobal()).getDynamicInvoker(INVOKE_UA_SETTER, 13.37 + new Callable<MethodHandle>() { 13.38 + @Override 13.39 + public MethodHandle call() { 13.40 + return Bootstrap.createDynamicInvoker("dyn:call", void.class, 13.41 + Object.class, Object.class, Object.class); 13.42 + } 13.43 + }); 13.44 + } 13.45 13.46 /** 13.47 * Constructor 13.48 @@ -191,7 +212,7 @@ 13.49 13.50 if (func instanceof ScriptFunction) { 13.51 try { 13.52 - return INVOKE_UA_GETTER.invokeExact(func, self); 13.53 + return getINVOKE_UA_GETTER().invokeExact(func, self); 13.54 } catch(final Error|RuntimeException t) { 13.55 throw t; 13.56 } catch(final Throwable t) { 13.57 @@ -208,7 +229,7 @@ 13.58 13.59 if (func instanceof ScriptFunction) { 13.60 try { 13.61 - INVOKE_UA_SETTER.invokeExact(func, self, value); 13.62 + getINVOKE_UA_SETTER().invokeExact(func, self, value); 13.63 } catch(final Error|RuntimeException t) { 13.64 throw t; 13.65 } catch(final Throwable t) {
14.1 --- a/src/jdk/nashorn/internal/runtime/linker/JavaAdapterClassLoader.java Wed Aug 07 16:38:44 2013 +0200 14.2 +++ b/src/jdk/nashorn/internal/runtime/linker/JavaAdapterClassLoader.java Thu Aug 08 16:38:32 2013 +0530 14.3 @@ -48,7 +48,7 @@ 14.4 private static final ProtectionDomain GENERATED_PROTECTION_DOMAIN = createGeneratedProtectionDomain(); 14.5 14.6 private final String className; 14.7 - private final byte[] classBytes; 14.8 + private volatile byte[] classBytes; 14.9 14.10 JavaAdapterClassLoader(String className, byte[] classBytes) { 14.11 this.className = className.replace('/', '.'); 14.12 @@ -56,6 +56,13 @@ 14.13 } 14.14 14.15 /** 14.16 + * clear classBytes after loading class. 14.17 + */ 14.18 + void clearClassBytes() { 14.19 + this.classBytes = null; 14.20 + } 14.21 + 14.22 + /** 14.23 * Loads the generated adapter class into the JVM. 14.24 * @param parentLoader the parent class loader for the generated class loader 14.25 * @return the generated adapter class 14.26 @@ -103,6 +110,7 @@ 14.27 @Override 14.28 protected Class<?> findClass(final String name) throws ClassNotFoundException { 14.29 if(name.equals(className)) { 14.30 + assert classBytes != null : "what? already cleared .class bytes!!"; 14.31 return defineClass(name, classBytes, 0, classBytes.length, GENERATED_PROTECTION_DOMAIN); 14.32 } else { 14.33 throw new ClassNotFoundException(name);
15.1 --- a/src/jdk/nashorn/internal/runtime/linker/JavaAdapterFactory.java Wed Aug 07 16:38:44 2013 +0200 15.2 +++ b/src/jdk/nashorn/internal/runtime/linker/JavaAdapterFactory.java Thu Aug 08 16:38:32 2013 +0530 15.3 @@ -224,7 +224,10 @@ 15.4 this.commonLoader = findCommonLoader(definingLoader); 15.5 final JavaAdapterBytecodeGenerator gen = new JavaAdapterBytecodeGenerator(superClass, interfaces, commonLoader, false); 15.6 this.autoConvertibleFromFunction = gen.isAutoConvertibleFromFunction(); 15.7 - this.instanceAdapterClass = gen.createAdapterClassLoader().generateClass(commonLoader); 15.8 + final JavaAdapterClassLoader jacl = gen.createAdapterClassLoader(); 15.9 + this.instanceAdapterClass = jacl.generateClass(commonLoader); 15.10 + // loaded Class - no need to keep class bytes around 15.11 + jacl.clearClassBytes(); 15.12 this.adapterGenerator = new JavaAdapterBytecodeGenerator(superClass, interfaces, commonLoader, true).createAdapterClassLoader(); 15.13 this.adaptationResult = AdaptationResult.SUCCESSFUL_RESULT; 15.14 }
16.1 --- a/test/script/basic/JDK-8020357.js Wed Aug 07 16:38:44 2013 +0200 16.2 +++ b/test/script/basic/JDK-8020357.js Thu Aug 08 16:38:32 2013 +0530 16.3 @@ -33,17 +33,6 @@ 16.4 16.5 var limit = Math.pow(2, UNSIGNED_INT_BITS)/BYTES_PER_INT_32 16.6 16.7 -try { 16.8 - // A value at or under the limit should either succeed if we have 16.9 - // enough heap, or throw an OutOfMemoryError if we don't. 16.10 - Int32Array(limit - 1) 16.11 -} catch(e) { 16.12 - if(!(e instanceof java.lang.OutOfMemoryError)) { 16.13 - // Only print an unexpected result; OutOfMemoryError is expected 16.14 - print(e) 16.15 - } 16.16 -} 16.17 - 16.18 // A value over the limit should throw a RangeError. 16.19 try { 16.20 Int32Array(limit)
17.1 --- a/test/src/jdk/nashorn/api/javaaccess/BooleanAccessTest.java Wed Aug 07 16:38:44 2013 +0200 17.2 +++ b/test/src/jdk/nashorn/api/javaaccess/BooleanAccessTest.java Thu Aug 08 16:38:32 2013 +0530 17.3 @@ -33,6 +33,7 @@ 17.4 import javax.script.ScriptEngineManager; 17.5 import javax.script.ScriptException; 17.6 import org.testng.TestNG; 17.7 +import org.testng.annotations.AfterClass; 17.8 import org.testng.annotations.BeforeClass; 17.9 import org.testng.annotations.Test; 17.10 17.11 @@ -44,7 +45,7 @@ 17.12 public class BooleanAccessTest { 17.13 17.14 private static ScriptEngine e = null; 17.15 - private static SharedObject o = new SharedObject(); 17.16 + private static SharedObject o = null; 17.17 17.18 public static void main(final String[] args) { 17.19 TestNG.main(args); 17.20 @@ -54,10 +55,17 @@ 17.21 public static void setUpClass() throws ScriptException { 17.22 final ScriptEngineManager m = new ScriptEngineManager(); 17.23 e = m.getEngineByName("nashorn"); 17.24 + o = new SharedObject(); 17.25 e.put("o", o); 17.26 e.eval("var SharedObject = Packages.jdk.nashorn.api.javaaccess.SharedObject;"); 17.27 } 17.28 17.29 + @AfterClass 17.30 + public static void tearDownClass() { 17.31 + e = null; 17.32 + o = null; 17.33 + } 17.34 + 17.35 @Test 17.36 public void accessFieldBoolean() throws ScriptException { 17.37 e.eval("var p_boolean = o.publicBoolean;");
18.1 --- a/test/src/jdk/nashorn/api/javaaccess/MethodAccessTest.java Wed Aug 07 16:38:44 2013 +0200 18.2 +++ b/test/src/jdk/nashorn/api/javaaccess/MethodAccessTest.java Thu Aug 08 16:38:32 2013 +0530 18.3 @@ -36,6 +36,7 @@ 18.4 import javax.script.ScriptEngineManager; 18.5 import javax.script.ScriptException; 18.6 import org.testng.TestNG; 18.7 +import org.testng.annotations.AfterClass; 18.8 import org.testng.annotations.BeforeClass; 18.9 import org.testng.annotations.Test; 18.10 18.11 @@ -47,7 +48,7 @@ 18.12 public class MethodAccessTest { 18.13 18.14 private static ScriptEngine e = null; 18.15 - private static SharedObject o = new SharedObject(); 18.16 + private static SharedObject o = null; 18.17 18.18 public static void main(final String[] args) { 18.19 TestNG.main(args); 18.20 @@ -57,12 +58,19 @@ 18.21 public static void setUpClass() throws ScriptException { 18.22 final ScriptEngineManager m = new ScriptEngineManager(); 18.23 e = m.getEngineByName("nashorn"); 18.24 + o = new SharedObject(); 18.25 o.setEngine(e); 18.26 e.put("o", o); 18.27 e.eval("var SharedObject = Packages.jdk.nashorn.api.javaaccess.SharedObject;"); 18.28 e.eval("var Person = Packages.jdk.nashorn.api.javaaccess.Person;"); 18.29 } 18.30 18.31 + @AfterClass 18.32 + public static void tearDownClass() { 18.33 + e = null; 18.34 + o = null; 18.35 + } 18.36 + 18.37 @Test 18.38 public void accessMethodthrowsCheckedException() throws ScriptException { 18.39 e.eval("try {" +
19.1 --- a/test/src/jdk/nashorn/api/javaaccess/NumberAccessTest.java Wed Aug 07 16:38:44 2013 +0200 19.2 +++ b/test/src/jdk/nashorn/api/javaaccess/NumberAccessTest.java Thu Aug 08 16:38:32 2013 +0530 19.3 @@ -33,6 +33,7 @@ 19.4 import javax.script.ScriptEngineManager; 19.5 import javax.script.ScriptException; 19.6 import org.testng.TestNG; 19.7 +import org.testng.annotations.AfterClass; 19.8 import org.testng.annotations.BeforeClass; 19.9 import org.testng.annotations.Test; 19.10 19.11 @@ -44,7 +45,7 @@ 19.12 public class NumberAccessTest { 19.13 19.14 private static ScriptEngine e = null; 19.15 - private static SharedObject o = new SharedObject(); 19.16 + private static SharedObject o = null; 19.17 19.18 public static void main(final String[] args) { 19.19 TestNG.main(args); 19.20 @@ -54,10 +55,17 @@ 19.21 public static void setUpClass() throws ScriptException { 19.22 final ScriptEngineManager m = new ScriptEngineManager(); 19.23 e = m.getEngineByName("nashorn"); 19.24 + o = new SharedObject(); 19.25 e.put("o", o); 19.26 e.eval("var SharedObject = Packages.jdk.nashorn.api.javaaccess.SharedObject;"); 19.27 } 19.28 19.29 + @AfterClass 19.30 + public static void tearDownClass() { 19.31 + e = null; 19.32 + o = null; 19.33 + } 19.34 + 19.35 // --------------------------------long 19.36 // tests------------------------------------ 19.37 @Test
20.1 --- a/test/src/jdk/nashorn/api/javaaccess/NumberBoxingTest.java Wed Aug 07 16:38:44 2013 +0200 20.2 +++ b/test/src/jdk/nashorn/api/javaaccess/NumberBoxingTest.java Thu Aug 08 16:38:32 2013 +0530 20.3 @@ -32,6 +32,7 @@ 20.4 import javax.script.ScriptEngineManager; 20.5 import javax.script.ScriptException; 20.6 import org.testng.TestNG; 20.7 +import org.testng.annotations.AfterClass; 20.8 import org.testng.annotations.BeforeClass; 20.9 import org.testng.annotations.Test; 20.10 20.11 @@ -43,7 +44,7 @@ 20.12 public class NumberBoxingTest { 20.13 20.14 private static ScriptEngine e = null; 20.15 - private static SharedObject o = new SharedObject(); 20.16 + private static SharedObject o = null; 20.17 20.18 public static void main(final String[] args) { 20.19 TestNG.main(args); 20.20 @@ -53,10 +54,17 @@ 20.21 public static void setUpClass() throws ScriptException { 20.22 final ScriptEngineManager m = new ScriptEngineManager(); 20.23 e = m.getEngineByName("nashorn"); 20.24 + o = new SharedObject(); 20.25 e.put("o", o); 20.26 e.eval("var SharedObject = Packages.jdk.nashorn.api.javaaccess.SharedObject;"); 20.27 } 20.28 20.29 + @AfterClass 20.30 + public static void tearDownClass() { 20.31 + e = null; 20.32 + o = null; 20.33 + } 20.34 + 20.35 // --------------------------------long 20.36 // tests------------------------------------ 20.37 @Test
21.1 --- a/test/src/jdk/nashorn/api/javaaccess/ObjectAccessTest.java Wed Aug 07 16:38:44 2013 +0200 21.2 +++ b/test/src/jdk/nashorn/api/javaaccess/ObjectAccessTest.java Thu Aug 08 16:38:32 2013 +0530 21.3 @@ -32,6 +32,7 @@ 21.4 import javax.script.ScriptEngineManager; 21.5 import javax.script.ScriptException; 21.6 import org.testng.TestNG; 21.7 +import org.testng.annotations.AfterClass; 21.8 import org.testng.annotations.BeforeClass; 21.9 import org.testng.annotations.Test; 21.10 21.11 @@ -43,7 +44,7 @@ 21.12 public class ObjectAccessTest { 21.13 21.14 private static ScriptEngine e = null; 21.15 - private static SharedObject o = new SharedObject(); 21.16 + private static SharedObject o = null; 21.17 21.18 public static void main(final String[] args) { 21.19 TestNG.main(args); 21.20 @@ -53,11 +54,18 @@ 21.21 public static void setUpClass() throws ScriptException { 21.22 final ScriptEngineManager m = new ScriptEngineManager(); 21.23 e = m.getEngineByName("nashorn"); 21.24 + o = new SharedObject(); 21.25 e.put("o", o); 21.26 e.eval("var SharedObject = Packages.jdk.nashorn.api.javaaccess.SharedObject;"); 21.27 e.eval("var Person = Packages.jdk.nashorn.api.javaaccess.Person;"); 21.28 } 21.29 21.30 + @AfterClass 21.31 + public static void tearDownClass() { 21.32 + e = null; 21.33 + o = null; 21.34 + } 21.35 + 21.36 @Test 21.37 public void accessFieldObject() throws ScriptException { 21.38 e.eval("var p_object = o.publicObject;");
22.1 --- a/test/src/jdk/nashorn/api/javaaccess/StringAccessTest.java Wed Aug 07 16:38:44 2013 +0200 22.2 +++ b/test/src/jdk/nashorn/api/javaaccess/StringAccessTest.java Thu Aug 08 16:38:32 2013 +0530 22.3 @@ -32,6 +32,7 @@ 22.4 import javax.script.ScriptEngineManager; 22.5 import javax.script.ScriptException; 22.6 import org.testng.TestNG; 22.7 +import org.testng.annotations.AfterClass; 22.8 import org.testng.annotations.BeforeClass; 22.9 import org.testng.annotations.Test; 22.10 22.11 @@ -43,7 +44,7 @@ 22.12 public class StringAccessTest { 22.13 22.14 private static ScriptEngine e = null; 22.15 - private static SharedObject o = new SharedObject(); 22.16 + private static SharedObject o = null; 22.17 22.18 public static void main(final String[] args) { 22.19 TestNG.main(args); 22.20 @@ -53,10 +54,17 @@ 22.21 public static void setUpClass() throws ScriptException { 22.22 final ScriptEngineManager m = new ScriptEngineManager(); 22.23 e = m.getEngineByName("nashorn"); 22.24 + o = new SharedObject(); 22.25 e.put("o", o); 22.26 e.eval("var SharedObject = Packages.jdk.nashorn.api.javaaccess.SharedObject;"); 22.27 } 22.28 22.29 + @AfterClass 22.30 + public static void tearDownClass() { 22.31 + e = null; 22.32 + o = null; 22.33 + } 22.34 + 22.35 @Test 22.36 public void accessFieldString() throws ScriptException { 22.37 e.eval("var p_string = o.publicString;");
23.1 --- a/test/src/jdk/nashorn/internal/codegen/CompilerTest.java Wed Aug 07 16:38:44 2013 +0200 23.2 +++ b/test/src/jdk/nashorn/internal/codegen/CompilerTest.java Thu Aug 08 16:38:32 2013 +0530 23.3 @@ -35,6 +35,8 @@ 23.4 import jdk.nashorn.internal.runtime.Source; 23.5 import jdk.nashorn.internal.runtime.options.Options; 23.6 import org.testng.Assert; 23.7 +import org.testng.annotations.AfterClass; 23.8 +import org.testng.annotations.BeforeClass; 23.9 import org.testng.annotations.Test; 23.10 23.11 /** 23.12 @@ -58,7 +60,8 @@ 23.13 private Context context; 23.14 private ScriptObject global; 23.15 23.16 - public CompilerTest() { 23.17 + @BeforeClass 23.18 + public void setupTest() { 23.19 final Options options = new Options("nashorn"); 23.20 options.set("anon.functions", true); 23.21 options.set("compile.only", true); 23.22 @@ -79,6 +82,12 @@ 23.23 this.global = context.createGlobal(); 23.24 } 23.25 23.26 + @AfterClass 23.27 + public void tearDownTest() { 23.28 + this.context = null; 23.29 + this.global = null; 23.30 + } 23.31 + 23.32 @Test 23.33 public void compileAllTests() { 23.34 if (TEST262) {
24.1 --- a/test/src/jdk/nashorn/internal/parser/ParserTest.java Wed Aug 07 16:38:44 2013 +0200 24.2 +++ b/test/src/jdk/nashorn/internal/parser/ParserTest.java Thu Aug 08 16:38:32 2013 +0530 24.3 @@ -28,10 +28,11 @@ 24.4 import java.io.File; 24.5 import jdk.nashorn.internal.runtime.Context; 24.6 import jdk.nashorn.internal.runtime.ErrorManager; 24.7 -import jdk.nashorn.internal.runtime.ScriptObject; 24.8 import jdk.nashorn.internal.runtime.Source; 24.9 import jdk.nashorn.internal.runtime.options.Options; 24.10 import org.testng.Assert; 24.11 +import org.testng.annotations.AfterClass; 24.12 +import org.testng.annotations.BeforeClass; 24.13 import org.testng.annotations.Test; 24.14 24.15 /** 24.16 @@ -54,9 +55,9 @@ 24.17 } 24.18 24.19 private Context context; 24.20 - private ScriptObject global; 24.21 24.22 - public ParserTest() { 24.23 + @BeforeClass 24.24 + public void setupTest() { 24.25 final Options options = new Options("nashorn"); 24.26 options.set("anon.functions", true); 24.27 options.set("parse.only", true); 24.28 @@ -64,7 +65,11 @@ 24.29 24.30 ErrorManager errors = new ErrorManager(); 24.31 this.context = new Context(options, errors, Thread.currentThread().getContextClassLoader()); 24.32 - this.global = context.createGlobal(); 24.33 + } 24.34 + 24.35 + @AfterClass 24.36 + public void tearDownTest() { 24.37 + this.context = null; 24.38 } 24.39 24.40 @Test 24.41 @@ -125,8 +130,6 @@ 24.42 log("Begin parsing " + file.getAbsolutePath()); 24.43 } 24.44 24.45 - final ScriptObject oldGlobal = Context.getGlobal(); 24.46 - final boolean globalChanged = (oldGlobal != global); 24.47 try { 24.48 final char[] buffer = Source.readFully(file); 24.49 boolean excluded = false; 24.50 @@ -150,9 +153,6 @@ 24.51 } 24.52 }; 24.53 errors.setLimit(0); 24.54 - if (globalChanged) { 24.55 - Context.setGlobal(global); 24.56 - } 24.57 final Source source = new Source(file.getAbsolutePath(), buffer); 24.58 new Parser(context.getEnv(), source, errors).parse(); 24.59 if (errors.getNumberOfErrors() > 0) { 24.60 @@ -167,10 +167,6 @@ 24.61 exp.printStackTrace(System.out); 24.62 } 24.63 failed++; 24.64 - } finally { 24.65 - if (globalChanged) { 24.66 - Context.setGlobal(oldGlobal); 24.67 - } 24.68 } 24.69 24.70 if (VERBOSE) {