< prev index next >

src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/Context.java

Print this page




   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);
 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 


< prev index next >