8 * particular file as subject to the "Classpath" exception as provided
9 * by Oracle in the LICENSE file that accompanied this code.
10 *
11 * This code is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 * version 2 for more details (a copy is included in the LICENSE file that
15 * accompanied this code).
16 *
17 * You should have received a copy of the GNU General Public License version
18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22 * or visit www.oracle.com if you need additional information or have any
23 * questions.
24 */
25
26 package jdk.nashorn.internal.runtime;
27
28 import static jdk.internal.org.objectweb.asm.Opcodes.V1_7;
29 import static jdk.nashorn.internal.codegen.CompilerConstants.CONSTANTS;
30 import static jdk.nashorn.internal.codegen.CompilerConstants.CREATE_PROGRAM_FUNCTION;
31 import static jdk.nashorn.internal.codegen.CompilerConstants.SOURCE;
32 import static jdk.nashorn.internal.codegen.CompilerConstants.STRICT_MODE;
33 import static jdk.nashorn.internal.runtime.CodeStore.newCodeStore;
34 import static jdk.nashorn.internal.runtime.ECMAErrors.typeError;
35 import static jdk.nashorn.internal.runtime.ScriptRuntime.UNDEFINED;
36 import static jdk.nashorn.internal.runtime.Source.sourceFor;
37
38 import java.io.File;
39 import java.io.InputStream;
40 import java.io.IOException;
41 import java.io.PrintWriter;
42 import java.lang.invoke.MethodHandle;
43 import java.lang.invoke.MethodHandles;
44 import java.lang.invoke.MethodType;
45 import java.lang.invoke.SwitchPoint;
46 import java.lang.ref.ReferenceQueue;
47 import java.lang.ref.SoftReference;
48 import java.lang.module.Configuration;
49 import java.lang.module.ModuleDescriptor;
50 import java.lang.module.ModuleFinder;
51 import java.lang.module.ModuleReader;
52 import java.lang.module.ModuleReference;
53 import java.lang.reflect.Field;
54 import java.lang.reflect.Modifier;
55 import java.net.MalformedURLException;
56 import java.net.URL;
57 import java.nio.file.Path;
58 import java.nio.file.Paths;
59 import java.security.AccessControlContext;
60 import java.security.AccessController;
61 import java.security.CodeSigner;
62 import java.security.CodeSource;
63 import java.security.Permissions;
64 import java.security.PrivilegedAction;
65 import java.security.PrivilegedActionException;
66 import java.security.PrivilegedExceptionAction;
67 import java.security.ProtectionDomain;
68 import java.util.Collection;
69 import java.util.HashMap;
70 import java.util.HashSet;
71 import java.util.LinkedHashMap;
72 import java.util.Map;
73 import java.util.Objects;
74 import java.util.Optional;
75 import java.util.Set;
76 import java.util.concurrent.ConcurrentHashMap;
77 import java.util.concurrent.ConcurrentMap;
78 import java.util.concurrent.atomic.AtomicLong;
79 import java.util.concurrent.atomic.AtomicReference;
80 import java.util.concurrent.atomic.LongAdder;
81 import java.util.function.Consumer;
82 import java.util.function.Supplier;
83 import java.util.logging.Level;
84 import java.util.stream.Collectors;
85 import java.util.stream.Stream;
86 import javax.script.ScriptEngine;
87 import jdk.dynalink.DynamicLinker;
88 import jdk.internal.org.objectweb.asm.ClassReader;
89 import jdk.internal.org.objectweb.asm.ClassWriter;
90 import jdk.internal.org.objectweb.asm.Opcodes;
91 import jdk.internal.org.objectweb.asm.util.CheckClassAdapter;
92 import jdk.nashorn.api.scripting.ClassFilter;
93 import jdk.nashorn.api.scripting.ScriptObjectMirror;
94 import jdk.nashorn.internal.WeakValueCache;
95 import jdk.nashorn.internal.codegen.Compiler;
96 import jdk.nashorn.internal.codegen.Compiler.CompilationPhases;
97 import jdk.nashorn.internal.codegen.ObjectClassGenerator;
98 import jdk.nashorn.internal.ir.FunctionNode;
99 import jdk.nashorn.internal.ir.debug.ASTWriter;
100 import jdk.nashorn.internal.ir.debug.PrintVisitor;
101 import jdk.nashorn.internal.lookup.MethodHandleFactory;
102 import jdk.nashorn.internal.objects.Global;
103 import jdk.nashorn.internal.parser.Parser;
104 import jdk.nashorn.internal.runtime.events.RuntimeEvent;
105 import jdk.nashorn.internal.runtime.linker.Bootstrap;
106 import jdk.nashorn.internal.runtime.logging.DebugLogger;
107 import jdk.nashorn.internal.runtime.logging.Loggable;
108 import jdk.nashorn.internal.runtime.logging.Logger;
109 import jdk.nashorn.internal.runtime.options.LoggingOption.LoggerInfo;
110 import jdk.nashorn.internal.runtime.options.Options;
111 import jdk.internal.misc.Unsafe;
112
113 /**
114 * This class manages the global state of execution. Context is immutable.
115 */
116 public final class Context {
117 // nashorn specific security runtime access permission names
118 /**
119 * Permission needed to pass arbitrary nashorn command line options when creating Context.
120 */
121 public static final String NASHORN_SET_CONFIG = "nashorn.setConfig";
122
123 /**
124 * Permission needed to create Nashorn Context instance.
125 */
126 public static final String NASHORN_CREATE_CONTEXT = "nashorn.createContext";
127
128 /**
129 * Permission needed to create Nashorn Global instance.
130 */
131 public static final String NASHORN_CREATE_GLOBAL = "nashorn.createGlobal";
301 @Override
302 public CodeInstaller getOnDemandCompilationInstaller() {
303 // Reuse this installer if we're within our limits.
304 if (usageCount < MAX_USAGES && bytesDefined < MAX_BYTES_DEFINED) {
305 return this;
306 }
307 return new NamedContextCodeInstaller(context, codeSource, context.createNewLoader());
308 }
309
310 @Override
311 public CodeInstaller getMultiClassCodeInstaller() {
312 // This installer is perfectly suitable for installing multiple classes that reference each other
313 // as it produces classes with resolvable names, all defined in a single class loader.
314 return this;
315 }
316 }
317
318 private final WeakValueCache<CodeSource, Class<?>> anonymousHostClasses = new WeakValueCache<>();
319
320 private static final class AnonymousContextCodeInstaller extends ContextCodeInstaller {
321 private static final Unsafe UNSAFE = Unsafe.getUnsafe();
322 private static final String ANONYMOUS_HOST_CLASS_NAME = Compiler.SCRIPTS_PACKAGE.replace('/', '.') + ".AnonymousHost";
323 private static final byte[] ANONYMOUS_HOST_CLASS_BYTES = getAnonymousHostClassBytes();
324
325 private final Class<?> hostClass;
326
327 private AnonymousContextCodeInstaller(final Context context, final CodeSource codeSource, final Class<?> hostClass) {
328 super(context, codeSource);
329 this.hostClass = hostClass;
330 }
331
332 @Override
333 public Class<?> install(final String className, final byte[] bytecode) {
334 ANONYMOUS_INSTALLED_SCRIPT_COUNT.increment();
335 return UNSAFE.defineAnonymousClass(hostClass, bytecode, null);
336 }
337
338 @Override
339 public CodeInstaller getOnDemandCompilationInstaller() {
340 // This code loader can be indefinitely reused for on-demand recompilations for the same code source.
341 return this;
342 }
343
344 @Override
345 public CodeInstaller getMultiClassCodeInstaller() {
346 // This code loader can not be used to install multiple classes that reference each other, as they
347 // would have no resolvable names. Therefore, in such situation we must revert to an installer that
348 // produces named classes.
349 return new NamedContextCodeInstaller(context, codeSource, context.createNewLoader());
350 }
351
352 private static byte[] getAnonymousHostClassBytes() {
353 final ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_FRAMES | ClassWriter.COMPUTE_MAXS);
354 cw.visit(V1_7, Opcodes.ACC_INTERFACE | Opcodes.ACC_ABSTRACT, ANONYMOUS_HOST_CLASS_NAME.replace('.', '/'), null, "java/lang/Object", null);
355 cw.visitEnd();
356 return cw.toByteArray();
357 }
358 }
359
360 /** Is Context global debug mode enabled ? */
361 public static final boolean DEBUG = Options.getBooleanProperty("nashorn.debug");
362
363 private static final ThreadLocal<Global> currentGlobal = new ThreadLocal<>();
364
365 // in-memory cache for loaded classes
366 private ClassCache classCache;
367
368 // persistent code store
369 private CodeStore codeStore;
370
371 // A factory for linking global properties as constant method handles. It is created when the first Global
372 // is created, and invalidated forever once the second global is created.
373 private final AtomicReference<GlobalConstants> globalConstantsRef = new AtomicReference<>();
374
|
8 * particular file as subject to the "Classpath" exception as provided
9 * by Oracle in the LICENSE file that accompanied this code.
10 *
11 * This code is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 * version 2 for more details (a copy is included in the LICENSE file that
15 * accompanied this code).
16 *
17 * You should have received a copy of the GNU General Public License version
18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22 * or visit www.oracle.com if you need additional information or have any
23 * questions.
24 */
25
26 package jdk.nashorn.internal.runtime;
27
28 import static jdk.internal.org.objectweb.asm.Opcodes.*;
29 import static jdk.nashorn.internal.codegen.CompilerConstants.CONSTANTS;
30 import static jdk.nashorn.internal.codegen.CompilerConstants.CREATE_PROGRAM_FUNCTION;
31 import static jdk.nashorn.internal.codegen.CompilerConstants.SOURCE;
32 import static jdk.nashorn.internal.codegen.CompilerConstants.STRICT_MODE;
33 import static jdk.nashorn.internal.runtime.CodeStore.newCodeStore;
34 import static jdk.nashorn.internal.runtime.ECMAErrors.typeError;
35 import static jdk.nashorn.internal.runtime.ScriptRuntime.UNDEFINED;
36 import static jdk.nashorn.internal.runtime.Source.sourceFor;
37
38 import java.io.File;
39 import java.io.InputStream;
40 import java.io.IOException;
41 import java.io.PrintWriter;
42 import java.lang.invoke.MethodHandle;
43 import java.lang.invoke.MethodHandles;
44 import java.lang.invoke.MethodHandles.Lookup.ClassOption;
45 import java.lang.invoke.MethodType;
46 import java.lang.invoke.SwitchPoint;
47 import java.lang.ref.ReferenceQueue;
48 import java.lang.ref.SoftReference;
49 import java.lang.module.Configuration;
50 import java.lang.module.ModuleDescriptor;
51 import java.lang.module.ModuleFinder;
52 import java.lang.module.ModuleReader;
53 import java.lang.module.ModuleReference;
54 import java.lang.reflect.Field;
55 import java.lang.reflect.Modifier;
56 import java.net.MalformedURLException;
57 import java.net.URL;
58 import java.nio.file.Path;
59 import java.nio.file.Paths;
60 import java.security.AccessControlContext;
61 import java.security.AccessController;
62 import java.security.CodeSigner;
63 import java.security.CodeSource;
64 import java.security.Permissions;
65 import java.security.PrivilegedAction;
66 import java.security.PrivilegedActionException;
67 import java.security.PrivilegedExceptionAction;
68 import java.security.ProtectionDomain;
69 import java.util.Collection;
70 import java.util.HashMap;
71 import java.util.LinkedHashMap;
72 import java.util.Map;
73 import java.util.Objects;
74 import java.util.Optional;
75 import java.util.Set;
76 import java.util.concurrent.ConcurrentHashMap;
77 import java.util.concurrent.ConcurrentMap;
78 import java.util.concurrent.atomic.AtomicLong;
79 import java.util.concurrent.atomic.AtomicReference;
80 import java.util.concurrent.atomic.LongAdder;
81 import java.util.function.Consumer;
82 import java.util.function.Supplier;
83 import java.util.logging.Level;
84 import java.util.stream.Collectors;
85 import java.util.stream.Stream;
86 import javax.script.ScriptEngine;
87
88 import jdk.dynalink.DynamicLinker;
89 import jdk.internal.org.objectweb.asm.ClassReader;
90 import jdk.internal.org.objectweb.asm.ClassWriter;
91 import jdk.internal.org.objectweb.asm.FieldVisitor;
92 import jdk.internal.org.objectweb.asm.MethodVisitor;
93 import jdk.internal.org.objectweb.asm.util.CheckClassAdapter;
94 import jdk.nashorn.api.scripting.ClassFilter;
95 import jdk.nashorn.api.scripting.ScriptObjectMirror;
96 import jdk.nashorn.internal.WeakValueCache;
97 import jdk.nashorn.internal.codegen.Compiler;
98 import jdk.nashorn.internal.codegen.Compiler.CompilationPhases;
99 import jdk.nashorn.internal.codegen.ObjectClassGenerator;
100 import jdk.nashorn.internal.ir.FunctionNode;
101 import jdk.nashorn.internal.ir.debug.ASTWriter;
102 import jdk.nashorn.internal.ir.debug.PrintVisitor;
103 import jdk.nashorn.internal.lookup.MethodHandleFactory;
104 import jdk.nashorn.internal.objects.Global;
105 import jdk.nashorn.internal.parser.Parser;
106 import jdk.nashorn.internal.runtime.events.RuntimeEvent;
107 import jdk.nashorn.internal.runtime.linker.Bootstrap;
108 import jdk.nashorn.internal.runtime.logging.DebugLogger;
109 import jdk.nashorn.internal.runtime.logging.Loggable;
110 import jdk.nashorn.internal.runtime.logging.Logger;
111 import jdk.nashorn.internal.runtime.options.LoggingOption.LoggerInfo;
112 import jdk.nashorn.internal.runtime.options.Options;
113
114 /**
115 * This class manages the global state of execution. Context is immutable.
116 */
117 public final class Context {
118 // nashorn specific security runtime access permission names
119 /**
120 * Permission needed to pass arbitrary nashorn command line options when creating Context.
121 */
122 public static final String NASHORN_SET_CONFIG = "nashorn.setConfig";
123
124 /**
125 * Permission needed to create Nashorn Context instance.
126 */
127 public static final String NASHORN_CREATE_CONTEXT = "nashorn.createContext";
128
129 /**
130 * Permission needed to create Nashorn Global instance.
131 */
132 public static final String NASHORN_CREATE_GLOBAL = "nashorn.createGlobal";
302 @Override
303 public CodeInstaller getOnDemandCompilationInstaller() {
304 // Reuse this installer if we're within our limits.
305 if (usageCount < MAX_USAGES && bytesDefined < MAX_BYTES_DEFINED) {
306 return this;
307 }
308 return new NamedContextCodeInstaller(context, codeSource, context.createNewLoader());
309 }
310
311 @Override
312 public CodeInstaller getMultiClassCodeInstaller() {
313 // This installer is perfectly suitable for installing multiple classes that reference each other
314 // as it produces classes with resolvable names, all defined in a single class loader.
315 return this;
316 }
317 }
318
319 private final WeakValueCache<CodeSource, Class<?>> anonymousHostClasses = new WeakValueCache<>();
320
321 private static final class AnonymousContextCodeInstaller extends ContextCodeInstaller {
322 private static final String ANONYMOUS_HOST_CLASS_NAME = Compiler.SCRIPTS_PACKAGE.replace('/', '.') + ".AnonymousHost";
323 private static final byte[] ANONYMOUS_HOST_CLASS_BYTES = getAnonymousHostClassBytes();
324
325 private final MethodHandles.Lookup hostLookup;
326
327 private AnonymousContextCodeInstaller(final Context context, final CodeSource codeSource, final Class<?> hostClass) {
328 super(context, codeSource);
329 this.hostLookup = (MethodHandles.Lookup)staticFieldValue(hostClass, "LOOKUP");
330 }
331
332 private static Object staticFieldValue(Class<?> c, String name) {
333 try {
334 return AccessController.doPrivileged(new PrivilegedExceptionAction<Object>() {
335 @Override
336 public Object run() throws Exception {
337 Field f = c.getDeclaredField(name);
338 return f.get(null);
339 }
340 });
341 } catch (PrivilegedActionException e) {
342 throw new InternalError(e.getCause());
343 }
344 }
345
346 @Override
347 public Class<?> install(final String className, final byte[] bytecode) {
348 try {
349 ANONYMOUS_INSTALLED_SCRIPT_COUNT.increment();
350 // Workaround: define it as a hidden nestmate so that the hostLookup can find private members
351 return hostLookup.defineHiddenClass(bytecode, true, ClassOption.NESTMATE).lookupClass();
352 } catch (IllegalAccessException e) {
353 throw new InternalError(e);
354 }
355 }
356
357 @Override
358 public void initialize(final Collection<Class<?>> classes, final Source source, final Object[] constants) {
359 AccessController.doPrivileged(new PrivilegedAction<Void>() {
360 @Override
361 public Void run() {
362 for (final Class<?> clazz : classes) {
363 try {
364 //use reflection to write source and constants table to installed classes
365 MethodHandle sourceField = hostLookup.findStaticSetter(clazz, SOURCE.symbolName(), Source.class);
366 sourceField.invokeExact(source);
367 MethodHandle constantsField = hostLookup.findStaticSetter(clazz, CONSTANTS.symbolName(), Object[].class);
368 constantsField.invokeExact(constants);
369 } catch (Throwable e) {
370 throw new RuntimeException(e);
371 }
372 }
373 return null;
374 }
375 });
376 }
377
378 @Override
379 public CodeInstaller getOnDemandCompilationInstaller() {
380 // This code loader can be indefinitely reused for on-demand recompilations for the same code source.
381 return this;
382 }
383
384 @Override
385 public CodeInstaller getMultiClassCodeInstaller() {
386 // This code loader can not be used to install multiple classes that reference each other, as they
387 // would have no resolvable names. Therefore, in such situation we must revert to an installer that
388 // produces named classes.
389 return new NamedContextCodeInstaller(context, codeSource, context.createNewLoader());
390 }
391
392 private static byte[] getAnonymousHostClassBytes() {
393 // Workaround: define a host class in a non-exported package.
394 // This should be replaced when there is a mechanism to define
395 // a hidden class in a given package of a given module.
396 final ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_FRAMES | ClassWriter.COMPUTE_MAXS);
397 final String cn = ANONYMOUS_HOST_CLASS_NAME.replace('.', '/');
398 cw.visit(V13, ACC_PUBLIC|ACC_INTERFACE |ACC_ABSTRACT, cn, null, "java/lang/Object", null);
399 {
400 FieldVisitor fv = cw.visitField(ACC_PUBLIC|ACC_STATIC|ACC_FINAL, "LOOKUP",
401 "Ljava/lang/invoke/MethodHandles$Lookup;", null, null);
402 fv.visitEnd();
403 }
404 {
405 MethodVisitor mv = cw.visitMethod(ACC_STATIC, "<clinit>", "()V", null, null);
406 mv.visitCode();
407 mv.visitMethodInsn(INVOKESTATIC, "java/lang/invoke/MethodHandles", "lookup",
408 "()Ljava/lang/invoke/MethodHandles$Lookup;", false);
409 mv.visitFieldInsn(PUTSTATIC, cn, "LOOKUP", "Ljava/lang/invoke/MethodHandles$Lookup;");
410 mv.visitInsn(RETURN);
411 mv.visitMaxs(0, 0);
412 mv.visitEnd();
413 }
414 cw.visitEnd();
415 return cw.toByteArray();
416 }
417 }
418
419 /** Is Context global debug mode enabled ? */
420 public static final boolean DEBUG = Options.getBooleanProperty("nashorn.debug");
421
422 private static final ThreadLocal<Global> currentGlobal = new ThreadLocal<>();
423
424 // in-memory cache for loaded classes
425 private ClassCache classCache;
426
427 // persistent code store
428 private CodeStore codeStore;
429
430 // A factory for linking global properties as constant method handles. It is created when the first Global
431 // is created, and invalidated forever once the second global is created.
432 private final AtomicReference<GlobalConstants> globalConstantsRef = new AtomicReference<>();
433
|