< prev index next >

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

Print this page

        

@@ -23,11 +23,11 @@
  * questions.
  */
 
 package jdk.nashorn.internal.runtime;
 
-import static jdk.internal.org.objectweb.asm.Opcodes.V1_7;
+import static jdk.internal.org.objectweb.asm.Opcodes.*;
 import static jdk.nashorn.internal.codegen.CompilerConstants.CONSTANTS;
 import static jdk.nashorn.internal.codegen.CompilerConstants.CREATE_PROGRAM_FUNCTION;
 import static jdk.nashorn.internal.codegen.CompilerConstants.SOURCE;
 import static jdk.nashorn.internal.codegen.CompilerConstants.STRICT_MODE;
 import static jdk.nashorn.internal.runtime.CodeStore.newCodeStore;

@@ -39,10 +39,11 @@
 import java.io.InputStream;
 import java.io.IOException;
 import java.io.PrintWriter;
 import java.lang.invoke.MethodHandle;
 import java.lang.invoke.MethodHandles;
+import java.lang.invoke.MethodHandles.Lookup.ClassOption;
 import java.lang.invoke.MethodType;
 import java.lang.invoke.SwitchPoint;
 import java.lang.ref.ReferenceQueue;
 import java.lang.ref.SoftReference;
 import java.lang.module.Configuration;

@@ -65,11 +66,10 @@
 import java.security.PrivilegedActionException;
 import java.security.PrivilegedExceptionAction;
 import java.security.ProtectionDomain;
 import java.util.Collection;
 import java.util.HashMap;
-import java.util.HashSet;
 import java.util.LinkedHashMap;
 import java.util.Map;
 import java.util.Objects;
 import java.util.Optional;
 import java.util.Set;

@@ -82,14 +82,16 @@
 import java.util.function.Supplier;
 import java.util.logging.Level;
 import java.util.stream.Collectors;
 import java.util.stream.Stream;
 import javax.script.ScriptEngine;
+
 import jdk.dynalink.DynamicLinker;
 import jdk.internal.org.objectweb.asm.ClassReader;
 import jdk.internal.org.objectweb.asm.ClassWriter;
-import jdk.internal.org.objectweb.asm.Opcodes;
+import jdk.internal.org.objectweb.asm.FieldVisitor;
+import jdk.internal.org.objectweb.asm.MethodVisitor;
 import jdk.internal.org.objectweb.asm.util.CheckClassAdapter;
 import jdk.nashorn.api.scripting.ClassFilter;
 import jdk.nashorn.api.scripting.ScriptObjectMirror;
 import jdk.nashorn.internal.WeakValueCache;
 import jdk.nashorn.internal.codegen.Compiler;

@@ -106,11 +108,10 @@
 import jdk.nashorn.internal.runtime.logging.DebugLogger;
 import jdk.nashorn.internal.runtime.logging.Loggable;
 import jdk.nashorn.internal.runtime.logging.Logger;
 import jdk.nashorn.internal.runtime.options.LoggingOption.LoggerInfo;
 import jdk.nashorn.internal.runtime.options.Options;
-import jdk.internal.misc.Unsafe;
 
 /**
  * This class manages the global state of execution. Context is immutable.
  */
 public final class Context {

@@ -316,25 +317,64 @@
     }
 
     private final WeakValueCache<CodeSource, Class<?>> anonymousHostClasses = new WeakValueCache<>();
 
     private static final class AnonymousContextCodeInstaller extends ContextCodeInstaller {
-        private static final Unsafe UNSAFE = Unsafe.getUnsafe();
         private static final String ANONYMOUS_HOST_CLASS_NAME = Compiler.SCRIPTS_PACKAGE.replace('/', '.') + ".AnonymousHost";
         private static final byte[] ANONYMOUS_HOST_CLASS_BYTES = getAnonymousHostClassBytes();
 
-        private final Class<?> hostClass;
+        private final MethodHandles.Lookup hostLookup;
 
         private AnonymousContextCodeInstaller(final Context context, final CodeSource codeSource, final Class<?> hostClass) {
             super(context, codeSource);
-            this.hostClass = hostClass;
+            this.hostLookup = (MethodHandles.Lookup)staticFieldValue(hostClass, "LOOKUP");
+        }
+
+        private static Object staticFieldValue(Class<?> c, String name) {
+            try {
+                return AccessController.doPrivileged(new PrivilegedExceptionAction<Object>() {
+                        @Override
+                        public Object run() throws Exception {
+                            Field f = c.getDeclaredField(name);
+                            return f.get(null);
+                        }
+                });
+            } catch (PrivilegedActionException e) {
+                throw new InternalError(e.getCause());
+            }
         }
 
         @Override
         public Class<?> install(final String className, final byte[] bytecode) {
+            try {
             ANONYMOUS_INSTALLED_SCRIPT_COUNT.increment();
-            return UNSAFE.defineAnonymousClass(hostClass, bytecode, null);
+                // Workaround: define it as a hidden nestmate so that the hostLookup can find private members
+                return hostLookup.defineHiddenClass(bytecode, true, ClassOption.NESTMATE, ClassOption.WEAK).lookupClass();
+            } catch (IllegalAccessException e) {
+                throw new InternalError(e);
+            }
+        }
+
+        @Override
+        public void initialize(final Collection<Class<?>> classes, final Source source, final Object[] constants) {
+            AccessController.doPrivileged(new PrivilegedAction<Void>() {
+                @Override
+                public Void run() {
+                    for (final Class<?> clazz : classes) {
+                        try {
+                            //use reflection to write source and constants table to installed classes
+                            MethodHandle sourceField = hostLookup.findStaticSetter(clazz, SOURCE.symbolName(), Source.class);
+                            sourceField.invokeExact(source);
+                            MethodHandle constantsField = hostLookup.findStaticSetter(clazz, CONSTANTS.symbolName(), Object[].class);
+                            constantsField.invokeExact(constants);
+                        } catch (Throwable e) {
+                            throw new RuntimeException(e);
+                        }
+                    }
+                    return null;
+                }
+            });
         }
 
         @Override
         public CodeInstaller getOnDemandCompilationInstaller() {
             // This code loader can be indefinitely reused for on-demand recompilations for the same code source.

@@ -348,12 +388,31 @@
             // produces named classes.
             return new NamedContextCodeInstaller(context, codeSource, context.createNewLoader());
         }
 
         private static byte[] getAnonymousHostClassBytes() {
+            // Workaround: define a host class in a non-exported package.
+            // This should be replaced when there is a mechanism to define
+            // a hidden class in a given package of a given module.
             final ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_FRAMES | ClassWriter.COMPUTE_MAXS);
-            cw.visit(V1_7, Opcodes.ACC_INTERFACE | Opcodes.ACC_ABSTRACT, ANONYMOUS_HOST_CLASS_NAME.replace('.', '/'), null, "java/lang/Object", null);
+            final String cn = ANONYMOUS_HOST_CLASS_NAME.replace('.', '/');
+            cw.visit(V13, ACC_PUBLIC|ACC_INTERFACE |ACC_ABSTRACT, cn, null, "java/lang/Object", null);
+            {
+                FieldVisitor fv = cw.visitField(ACC_PUBLIC|ACC_STATIC|ACC_FINAL, "LOOKUP",
+                        "Ljava/lang/invoke/MethodHandles$Lookup;", null, null);
+                fv.visitEnd();
+            }
+            {
+                MethodVisitor mv = cw.visitMethod(ACC_STATIC, "<clinit>", "()V", null, null);
+                mv.visitCode();
+                mv.visitMethodInsn(INVOKESTATIC, "java/lang/invoke/MethodHandles", "lookup",
+                        "()Ljava/lang/invoke/MethodHandles$Lookup;", false);
+                mv.visitFieldInsn(PUTSTATIC, cn, "LOOKUP", "Ljava/lang/invoke/MethodHandles$Lookup;");
+                mv.visitInsn(RETURN);
+                mv.visitMaxs(0, 0);
+                mv.visitEnd();
+            }
             cw.visitEnd();
             return cw.toByteArray();
         }
     }
 
< prev index next >