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, ClassOption.WEAK).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 |