changeset 24745:3a6e1477362b

8041434: Add synchronization to the common global constants structure Reviewed-by: attila, hannesw
author lagergren
date Wed, 23 Apr 2014 17:37:41 +0200
parents 5290da85fc3d
children 4b8db7796091
files nashorn/bin/runopt.sh nashorn/src/jdk/nashorn/internal/codegen/ApplySpecialization.java nashorn/src/jdk/nashorn/internal/codegen/Attr.java nashorn/src/jdk/nashorn/internal/codegen/ClassEmitter.java nashorn/src/jdk/nashorn/internal/codegen/CodeGenerator.java nashorn/src/jdk/nashorn/internal/codegen/CompilationEnvironment.java nashorn/src/jdk/nashorn/internal/codegen/CompilationPhase.java nashorn/src/jdk/nashorn/internal/codegen/Compiler.java nashorn/src/jdk/nashorn/internal/codegen/FinalizeTypes.java nashorn/src/jdk/nashorn/internal/codegen/FindScopeDepths.java nashorn/src/jdk/nashorn/internal/codegen/FoldConstants.java nashorn/src/jdk/nashorn/internal/codegen/Lower.java nashorn/src/jdk/nashorn/internal/codegen/MethodEmitter.java nashorn/src/jdk/nashorn/internal/codegen/ObjectClassGenerator.java nashorn/src/jdk/nashorn/internal/codegen/RangeAnalyzer.java nashorn/src/jdk/nashorn/internal/ir/debug/JSONWriter.java nashorn/src/jdk/nashorn/internal/lookup/MethodHandleFactory.java nashorn/src/jdk/nashorn/internal/objects/Global.java nashorn/src/jdk/nashorn/internal/objects/NativeFunction.java nashorn/src/jdk/nashorn/internal/parser/Parser.java nashorn/src/jdk/nashorn/internal/runtime/AccessorProperty.java nashorn/src/jdk/nashorn/internal/runtime/CompiledFunction.java nashorn/src/jdk/nashorn/internal/runtime/Context.java nashorn/src/jdk/nashorn/internal/runtime/GlobalConstants.java nashorn/src/jdk/nashorn/internal/runtime/RecompilableScriptFunctionData.java nashorn/src/jdk/nashorn/internal/runtime/ScriptFunction.java nashorn/src/jdk/nashorn/internal/runtime/ScriptObject.java nashorn/src/jdk/nashorn/internal/runtime/ScriptRuntime.java nashorn/src/jdk/nashorn/internal/runtime/arrays/ContinuousArrayData.java nashorn/src/jdk/nashorn/internal/runtime/arrays/TypedArrayData.java nashorn/src/jdk/nashorn/internal/runtime/events/RecompilationEvent.java nashorn/src/jdk/nashorn/internal/runtime/logging/DebugLogger.java nashorn/src/jdk/nashorn/internal/runtime/logging/Loggable.java nashorn/src/jdk/nashorn/tools/Shell.java nashorn/test/src/jdk/nashorn/internal/parser/ParserTest.java
diffstat 35 files changed, 409 insertions(+), 385 deletions(-) [+]
line wrap: on
line diff
--- a/nashorn/bin/runopt.sh	Wed Apr 23 16:13:47 2014 +0200
+++ b/nashorn/bin/runopt.sh	Wed Apr 23 17:37:41 2014 +0200
@@ -25,6 +25,7 @@
 -cp $CLASSPATH:../build/test/classes/ \
 jdk.nashorn.tools.Shell ${@}
 
+#-Djava.security.manager= -Djava.security.policy=$DIR/build/nashorn.policy \
 #-XX:+ShowHiddenFrames \
 #-XX:+PrintOptoAssembly \
 #-XX:-TieredCompilation \
--- a/nashorn/src/jdk/nashorn/internal/codegen/ApplySpecialization.java	Wed Apr 23 16:13:47 2014 +0200
+++ b/nashorn/src/jdk/nashorn/internal/codegen/ApplySpecialization.java	Wed Apr 23 17:37:41 2014 +0200
@@ -48,6 +48,7 @@
 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.Context;
 import jdk.nashorn.internal.runtime.RecompilableScriptFunctionData;
 import jdk.nashorn.internal.runtime.options.Options;
 
@@ -106,15 +107,16 @@
      * applies as calls if they just pass on the "arguments" array and
      * "arguments" doesn't escape.
      *
+     * @param context             context
      * @param data                recompilable script function data, which contains e.g. needs callee information
      * @param functionNode        functionNode
      * @param actualCallSiteType  actual call site type that we use (not Object[] varargs)
      */
-    public ApplySpecialization(final RecompilableScriptFunctionData data, final FunctionNode functionNode, final MethodType actualCallSiteType) {
+    public ApplySpecialization(final Context context, final RecompilableScriptFunctionData data, final FunctionNode functionNode, final MethodType actualCallSiteType) {
         this.data               = data;
         this.functionNode       = functionNode;
         this.actualCallSiteType = actualCallSiteType;
-        this.log                = initLogger(Global.instance());
+        this.log                = initLogger(context);
     }
 
     @Override
@@ -123,8 +125,8 @@
     }
 
     @Override
-    public DebugLogger initLogger(final Global global) {
-        return global.getLogger(this.getClass());
+    public DebugLogger initLogger(final Context context) {
+        return context.getLogger(this.getClass());
     }
 
     /**
--- a/nashorn/src/jdk/nashorn/internal/codegen/Attr.java	Wed Apr 23 16:13:47 2014 +0200
+++ b/nashorn/src/jdk/nashorn/internal/codegen/Attr.java	Wed Apr 23 17:37:41 2014 +0200
@@ -100,7 +100,6 @@
 import jdk.nashorn.internal.ir.WithNode;
 import jdk.nashorn.internal.ir.visitor.NodeOperatorVisitor;
 import jdk.nashorn.internal.ir.visitor.NodeVisitor;
-import jdk.nashorn.internal.objects.Global;
 import jdk.nashorn.internal.parser.TokenType;
 import jdk.nashorn.internal.runtime.Context;
 import jdk.nashorn.internal.runtime.Debug;
@@ -164,7 +163,7 @@
         this.temporarySymbols = temporarySymbols;
         this.localDefs        = new ArrayDeque<>();
         this.localUses        = new ArrayDeque<>();
-        this.log              = initLogger(Global.instance());
+        this.log              = initLogger(env.getContext());
         this.debug            = log.isEnabled();
     }
 
@@ -174,8 +173,8 @@
     }
 
     @Override
-    public DebugLogger initLogger(final Global global) {
-        return global.getLogger(this.getClass());
+    public DebugLogger initLogger(final Context context) {
+        return context.getLogger(this.getClass());
     }
 
     @Override
--- a/nashorn/src/jdk/nashorn/internal/codegen/ClassEmitter.java	Wed Apr 23 16:13:47 2014 +0200
+++ b/nashorn/src/jdk/nashorn/internal/codegen/ClassEmitter.java	Wed Apr 23 17:37:41 2014 +0200
@@ -70,7 +70,6 @@
 import jdk.nashorn.internal.runtime.Context;
 import jdk.nashorn.internal.runtime.PropertyMap;
 import jdk.nashorn.internal.runtime.RewriteException;
-import jdk.nashorn.internal.runtime.ScriptEnvironment;
 import jdk.nashorn.internal.runtime.ScriptObject;
 import jdk.nashorn.internal.runtime.Source;
 
@@ -128,7 +127,7 @@
     protected final ClassWriter cw;
 
     /** The script environment */
-    protected final ScriptEnvironment env;
+    protected final Context context;
 
     /** Compile unit class name. */
     private String unitClassName;
@@ -143,10 +142,8 @@
      * @param env script environment
      * @param cw  ASM classwriter
      */
-    private ClassEmitter(final ScriptEnvironment env, final ClassWriter cw) {
-        assert env != null;
-
-        this.env            = env;
+    private ClassEmitter(final Context context, final ClassWriter cw) {
+        this.context        = context;
         this.cw             = cw;
         this.methodsStarted = new HashSet<>();
     }
@@ -159,8 +156,8 @@
      * @param superClassName  super class name for class
      * @param interfaceNames  names of interfaces implemented by this class, or null if none
      */
-    ClassEmitter(final ScriptEnvironment env, final String className, final String superClassName, final String... interfaceNames) {
-        this(env, new ClassWriter(ClassWriter.COMPUTE_FRAMES | ClassWriter.COMPUTE_MAXS));
+    ClassEmitter(final Context context, final String className, final String superClassName, final String... interfaceNames) {
+        this(context, new ClassWriter(ClassWriter.COMPUTE_FRAMES | ClassWriter.COMPUTE_MAXS));
         cw.visit(V1_7, ACC_PUBLIC | ACC_SUPER, className, null, superClassName, interfaceNames);
     }
 
@@ -172,8 +169,8 @@
      * @param unitClassName Compile unit class name.
      * @param strictMode    Should we generate this method in strict mode
      */
-    ClassEmitter(final ScriptEnvironment env, final String sourceName, final String unitClassName, final boolean strictMode) {
-        this(env,
+    ClassEmitter(final Context context, final String sourceName, final String unitClassName, final boolean strictMode) {
+        this(context,
              new ClassWriter(ClassWriter.COMPUTE_FRAMES | ClassWriter.COMPUTE_MAXS) {
                 private static final String OBJECT_CLASS  = "java/lang/Object";
 
@@ -199,6 +196,10 @@
         defineCommonStatics(strictMode);
     }
 
+    Context getContext() {
+        return context;
+    }
+
     /**
      * Returns the name of the compile unit class name.
      * @return the name of the compile unit class name.
@@ -394,13 +395,6 @@
     }
 
     /**
-     * @return env used for class emission
-     */
-    ScriptEnvironment getEnv() {
-        return env;
-    }
-
-    /**
      * Call back from MethodEmitter for method start
      *
      * @see MethodEmitter
--- a/nashorn/src/jdk/nashorn/internal/codegen/CodeGenerator.java	Wed Apr 23 16:13:47 2014 +0200
+++ b/nashorn/src/jdk/nashorn/internal/codegen/CodeGenerator.java	Wed Apr 23 17:37:41 2014 +0200
@@ -240,7 +240,7 @@
         super(new CodeGeneratorLexicalContext());
         this.compiler      = compiler;
         this.callSiteFlags = compiler.getEnv()._callsite_flags;
-        this.log           = initLogger(Global.instance());
+        this.log           = initLogger(compiler.getCompilationEnvironment().getContext());
     }
 
     @Override
@@ -249,8 +249,8 @@
     }
 
     @Override
-    public DebugLogger initLogger(final Global global) {
-        return global.getLogger(this.getClass());
+    public DebugLogger initLogger(final Context context) {
+        return context.getLogger(this.getClass());
     }
 
     /**
--- a/nashorn/src/jdk/nashorn/internal/codegen/CompilationEnvironment.java	Wed Apr 23 16:13:47 2014 +0200
+++ b/nashorn/src/jdk/nashorn/internal/codegen/CompilationEnvironment.java	Wed Apr 23 17:37:41 2014 +0200
@@ -34,6 +34,7 @@
 import java.util.List;
 import java.util.Map;
 import java.util.Set;
+
 import jdk.nashorn.internal.codegen.types.Type;
 import jdk.nashorn.internal.ir.AccessNode;
 import jdk.nashorn.internal.ir.Expression;
@@ -42,6 +43,7 @@
 import jdk.nashorn.internal.ir.IndexNode;
 import jdk.nashorn.internal.ir.Optimistic;
 import jdk.nashorn.internal.objects.NativeArray;
+import jdk.nashorn.internal.runtime.Context;
 import jdk.nashorn.internal.runtime.JSType;
 import jdk.nashorn.internal.runtime.FindProperty;
 import jdk.nashorn.internal.runtime.Property;
@@ -57,6 +59,8 @@
     private final CompilationPhases phases;
     private final boolean optimistic;
 
+    private final Context context;
+
     private final ParamTypeMap paramTypes;
 
     private RecompilableScriptFunctionData compiledFunction;
@@ -176,17 +180,21 @@
 
     /**
      * Constructor
+     * @param context context
      * @param phases compilation phases
      * @param strict strict mode
      */
     public CompilationEnvironment(
+        final Context context,
         final CompilationPhases phases,
         final boolean strict) {
-        this(phases, null, null, null, null, null, strict, false);
+        this(context, phases, null, null, null, null, null, strict, false);
     }
 
     /**
      * Constructor for compilation environment of the rest-of method
+     *
+     * @param context context
      * @param phases compilation phases
      * @param strict strict mode
      * @param compiledFunction the function being compiled
@@ -200,19 +208,22 @@
      * @param onDemand is this an on demand compilation
      */
     public CompilationEnvironment(
-        final CompilationPhases phases,
-        final boolean strict,
-        final RecompilableScriptFunctionData compiledFunction,
-        final ScriptObject runtimeScope,
-        final ParamTypeMap paramTypeMap,
-        final Map<Integer, Type> invalidatedProgramPoints,
-        final int[] continuationEntryPoint,
-        final boolean onDemand) {
-            this(phases, paramTypeMap, invalidatedProgramPoints, compiledFunction, runtimeScope, continuationEntryPoint, strict, onDemand);
+            final Context context,
+            final CompilationPhases phases,
+            final boolean strict,
+            final RecompilableScriptFunctionData compiledFunction,
+            final ScriptObject runtimeScope,
+            final ParamTypeMap paramTypeMap,
+            final Map<Integer, Type> invalidatedProgramPoints,
+            final int[] continuationEntryPoint,
+            final boolean onDemand) {
+            this(context, phases, paramTypeMap, invalidatedProgramPoints, compiledFunction, runtimeScope, continuationEntryPoint, strict, onDemand);
     }
 
     /**
      * Constructor
+     *
+     * @param context context
      * @param phases compilation phases
      * @param strict strict mode
      * @param compiledFunction recompiled function
@@ -225,17 +236,19 @@
      * @param onDemand is this an on demand compilation
      */
     public CompilationEnvironment(
-        final CompilationPhases phases,
-        final boolean strict,
-        final RecompilableScriptFunctionData compiledFunction,
-        final ScriptObject runtimeScope,
-        final ParamTypeMap paramTypeMap,
-        final Map<Integer, Type> invalidatedProgramPoints,
-        final boolean onDemand) {
-        this(phases, paramTypeMap, invalidatedProgramPoints, compiledFunction, runtimeScope, null, strict, onDemand);
+            final Context context,
+            final CompilationPhases phases,
+            final boolean strict,
+            final RecompilableScriptFunctionData compiledFunction,
+            final ScriptObject runtimeScope,
+            final ParamTypeMap paramTypeMap,
+            final Map<Integer, Type> invalidatedProgramPoints,
+            final boolean onDemand) {
+        this(context, phases, paramTypeMap, invalidatedProgramPoints, compiledFunction, runtimeScope, null, strict, onDemand);
     }
 
     private CompilationEnvironment(
+            final Context context,
             final CompilationPhases phases,
             final ParamTypeMap paramTypes,
             final Map<Integer, Type> invalidatedProgramPoints,
@@ -244,6 +257,7 @@
             final int[] continuationEntryPoints,
             final boolean strict,
             final boolean onDemand) {
+        this.context                  = context;
         this.phases                   = phases;
         this.paramTypes               = paramTypes;
         this.continuationEntryPoints  = continuationEntryPoints;
@@ -261,6 +275,10 @@
         assert !isCompileRestOf() || invalidatedProgramPoints != null && containsAll(invalidatedProgramPoints.keySet(), continuationEntryPoints);
     }
 
+    Context getContext() {
+        return context;
+    }
+
     private static boolean containsAll(final Set<Integer> set, final int[] array) {
         for (int i = 0; i < array.length; ++i) {
             if (!set.contains(array[i])) {
--- a/nashorn/src/jdk/nashorn/internal/codegen/CompilationPhase.java	Wed Apr 23 16:13:47 2014 +0200
+++ b/nashorn/src/jdk/nashorn/internal/codegen/CompilationPhase.java	Wed Apr 23 17:37:41 2014 +0200
@@ -53,7 +53,6 @@
 import jdk.nashorn.internal.ir.debug.ASTWriter;
 import jdk.nashorn.internal.ir.debug.PrintVisitor;
 import jdk.nashorn.internal.ir.visitor.NodeVisitor;
-import jdk.nashorn.internal.objects.Global;
 import jdk.nashorn.internal.runtime.ScriptEnvironment;
 import jdk.nashorn.internal.runtime.Timing;
 
@@ -69,7 +68,7 @@
     CONSTANT_FOLDING_PHASE(EnumSet.of(INITIALIZED, PARSED)) {
         @Override
         FunctionNode transform(final Compiler compiler, final FunctionNode fn) {
-            return (FunctionNode)fn.accept(new FoldConstants());
+            return (FunctionNode)fn.accept(new FoldConstants(compiler.getCompilationEnvironment()));
         }
 
         @Override
@@ -88,7 +87,7 @@
     LOWERING_PHASE(EnumSet.of(INITIALIZED, PARSED, CONSTANT_FOLDED)) {
         @Override
         FunctionNode transform(final Compiler compiler, final FunctionNode fn) {
-            return (FunctionNode)fn.accept(new Lower(compiler.getCodeInstaller()));
+            return (FunctionNode)fn.accept(new Lower(compiler));
         }
 
         @Override
@@ -191,7 +190,7 @@
                 return fn;
             }
 
-            FunctionNode newFunctionNode = (FunctionNode)fn.accept(new RangeAnalyzer());
+            FunctionNode newFunctionNode = (FunctionNode)fn.accept(new RangeAnalyzer(compiler.getCompilationEnvironment()));
             final List<ReturnNode> returns = new ArrayList<>();
 
             newFunctionNode = (FunctionNode)newFunctionNode.accept(new NodeVisitor<LexicalContext>(new LexicalContext()) {
@@ -225,7 +224,7 @@
 
                 @Override
                 public Node leaveDefault(final Node node) {
-                    if(node instanceof Expression) {
+                    if (node instanceof Expression) {
                         final Expression expr = (Expression)node;
                         final Symbol symbol = expr.getSymbol();
                         if (symbol != null) {
@@ -238,7 +237,7 @@
 
                             final Type rangeType  = range.getType();
                             if (!rangeType.isUnknown() && !Type.areEquivalent(symbolType, rangeType) && Type.widest(symbolType, rangeType) == symbolType) { //we can narrow range
-                                Global.instance().getLogger(RangeAnalyzer.class).info("[", lc.getCurrentFunction().getName(), "] ", symbol, " can be ", range.getType(), " ", symbol.getRange());
+                                compiler.getCompilationEnvironment().getContext().getLogger(RangeAnalyzer.class).info("[", lc.getCurrentFunction().getName(), "] ", symbol, " can be ", range.getType(), " ", symbol.getRange());
                                 return expr.setSymbol(lc, symbol.setTypeOverrideShared(range.getType(), compiler.getTemporarySymbols()));
                             }
                         }
@@ -284,7 +283,7 @@
         FunctionNode transform(final Compiler compiler, final FunctionNode fn) {
             final ScriptEnvironment env = compiler.getEnv();
 
-            final FunctionNode newFunctionNode = (FunctionNode)fn.accept(new FinalizeTypes());
+            final FunctionNode newFunctionNode = (FunctionNode)fn.accept(new FinalizeTypes(compiler.getCompilationEnvironment()));
 
             if (env._print_lower_ast) {
                 env.getErr().println(new ASTWriter(newFunctionNode));
--- a/nashorn/src/jdk/nashorn/internal/codegen/Compiler.java	Wed Apr 23 16:13:47 2014 +0200
+++ b/nashorn/src/jdk/nashorn/internal/codegen/Compiler.java	Wed Apr 23 17:37:41 2014 +0200
@@ -61,8 +61,8 @@
 import jdk.nashorn.internal.ir.TemporarySymbols;
 import jdk.nashorn.internal.ir.debug.ClassHistogramElement;
 import jdk.nashorn.internal.ir.debug.ObjectSizeCalculator;
-import jdk.nashorn.internal.objects.Global;
 import jdk.nashorn.internal.runtime.CodeInstaller;
+import jdk.nashorn.internal.runtime.Context;
 import jdk.nashorn.internal.runtime.RecompilableScriptFunctionData;
 import jdk.nashorn.internal.runtime.ScriptEnvironment;
 import jdk.nashorn.internal.runtime.Source;
@@ -150,14 +150,12 @@
         this.constantData   = new ConstantData();
         this.compileUnits   = new TreeSet<>();
         this.bytecode       = new LinkedHashMap<>();
-        this.log            = initLogger(Global.instance());
+        this.log            = initLogger(compilationEnv.getContext());
 
-        synchronized (Compiler.class) {
-            if (!initialized) {
-                initialized = true;
-                if (!ScriptEnvironment.globalOptimistic()) {
-                    log.warning("Running without optimistic types. This is a configuration that may be deprecated.");
-                }
+        if (!initialized) {
+            initialized = true;
+            if (!ScriptEnvironment.globalOptimistic()) {
+                log.warning("Running without optimistic types. This is a configuration that may be deprecated.");
             }
         }
     }
@@ -177,7 +175,7 @@
      * @param scriptEnv script environment
      */
     public Compiler(final ScriptEnvironment scriptEnv) {
-        this(new CompilationEnvironment(CompilationPhases.EAGER, scriptEnv._strict), scriptEnv, null);
+        this(new CompilationEnvironment(Context.getContext(), CompilationPhases.EAGER, scriptEnv._strict), scriptEnv, null);
     }
 
     @Override
@@ -186,8 +184,8 @@
     }
 
     @Override
-    public DebugLogger initLogger(final Global global) {
-        return global.getLogger(this.getClass());
+    public DebugLogger initLogger(final Context context) {
+        return context.getLogger(this.getClass());
     }
 
     private void printMemoryUsage(final String phaseName, final FunctionNode functionNode) {
@@ -500,7 +498,7 @@
     }
 
     private CompileUnit initCompileUnit(final String unitClassName, final long initialWeight) {
-        final ClassEmitter classEmitter = new ClassEmitter(scriptEnv, sourceName, unitClassName, compilationEnv.isStrict());
+        final ClassEmitter classEmitter = new ClassEmitter(compilationEnv.getContext(), sourceName, unitClassName, compilationEnv.isStrict());
         final CompileUnit  compileUnit  = new CompileUnit(unitClassName, classEmitter, initialWeight);
 
         classEmitter.begin();
--- a/nashorn/src/jdk/nashorn/internal/codegen/FinalizeTypes.java	Wed Apr 23 16:13:47 2014 +0200
+++ b/nashorn/src/jdk/nashorn/internal/codegen/FinalizeTypes.java	Wed Apr 23 17:37:41 2014 +0200
@@ -42,9 +42,9 @@
 import jdk.nashorn.internal.ir.Symbol;
 import jdk.nashorn.internal.ir.UnaryNode;
 import jdk.nashorn.internal.ir.visitor.NodeOperatorVisitor;
-import jdk.nashorn.internal.objects.Global;
 import jdk.nashorn.internal.parser.Token;
 import jdk.nashorn.internal.parser.TokenType;
+import jdk.nashorn.internal.runtime.Context;
 import jdk.nashorn.internal.runtime.logging.DebugLogger;
 import jdk.nashorn.internal.runtime.logging.Loggable;
 import jdk.nashorn.internal.runtime.logging.Logger;
@@ -66,9 +66,9 @@
 
     private final DebugLogger log;
 
-    FinalizeTypes() {
+    FinalizeTypes(final CompilationEnvironment env) {
         super(new LexicalContext());
-        this.log = initLogger(Global.instance());
+        this.log = initLogger(env.getContext());
     }
 
     @Override
@@ -77,8 +77,8 @@
     }
 
     @Override
-    public DebugLogger initLogger(final Global global) {
-        return global.getLogger(this.getClass());
+    public DebugLogger initLogger(final Context context) {
+        return context.getLogger(this.getClass());
     }
 
     @Override
--- a/nashorn/src/jdk/nashorn/internal/codegen/FindScopeDepths.java	Wed Apr 23 16:13:47 2014 +0200
+++ b/nashorn/src/jdk/nashorn/internal/codegen/FindScopeDepths.java	Wed Apr 23 17:37:41 2014 +0200
@@ -42,7 +42,7 @@
 import jdk.nashorn.internal.ir.Node;
 import jdk.nashorn.internal.ir.Symbol;
 import jdk.nashorn.internal.ir.visitor.NodeVisitor;
-import jdk.nashorn.internal.objects.Global;
+import jdk.nashorn.internal.runtime.Context;
 import jdk.nashorn.internal.runtime.PropertyMap;
 import jdk.nashorn.internal.runtime.RecompilableScriptFunctionData;
 import jdk.nashorn.internal.runtime.logging.DebugLogger;
@@ -70,7 +70,7 @@
         super(new LexicalContext());
         this.compiler = compiler;
         this.env      = compiler.getCompilationEnvironment();
-        this.log      = initLogger(Global.instance());
+        this.log      = initLogger(compiler.getCompilationEnvironment().getContext());
     }
 
     @Override
@@ -79,8 +79,8 @@
     }
 
     @Override
-    public DebugLogger initLogger(final Global global) {
-        return global.getLogger(this.getClass());
+    public DebugLogger initLogger(final Context context) {
+        return context.getLogger(this.getClass());
     }
 
     static int findScopesToStart(final LexicalContext lc, final FunctionNode fn, final Block block) {
@@ -187,6 +187,7 @@
         final String      allocatorClassName = Compiler.binaryName(getClassName(fieldCount));
         final PropertyMap allocatorMap       = PropertyMap.newMap(null, 0, fieldCount, 0);
         final RecompilableScriptFunctionData data = new RecompilableScriptFunctionData(
+                compiler.getCompilationEnvironment().getContext(),
                 newFunctionNode,
                 compiler.getCodeInstaller(),
                 allocatorClassName,
--- a/nashorn/src/jdk/nashorn/internal/codegen/FoldConstants.java	Wed Apr 23 16:13:47 2014 +0200
+++ b/nashorn/src/jdk/nashorn/internal/codegen/FoldConstants.java	Wed Apr 23 17:37:41 2014 +0200
@@ -45,7 +45,7 @@
 import jdk.nashorn.internal.ir.UnaryNode;
 import jdk.nashorn.internal.ir.VarNode;
 import jdk.nashorn.internal.ir.visitor.NodeVisitor;
-import jdk.nashorn.internal.objects.Global;
+import jdk.nashorn.internal.runtime.Context;
 import jdk.nashorn.internal.runtime.JSType;
 import jdk.nashorn.internal.runtime.ScriptRuntime;
 import jdk.nashorn.internal.runtime.logging.DebugLogger;
@@ -60,9 +60,9 @@
 
     private final DebugLogger log;
 
-    FoldConstants() {
+    FoldConstants(final CompilationEnvironment env) {
         super(new LexicalContext());
-        this.log = initLogger(Global.instance());
+        this.log = initLogger(env.getContext());
     }
 
     @Override
@@ -71,8 +71,8 @@
     }
 
     @Override
-    public DebugLogger initLogger(final Global global) {
-        return global.getLogger(this.getClass());
+    public DebugLogger initLogger(final Context context) {
+        return context.getLogger(this.getClass());
     }
 
     @Override
--- a/nashorn/src/jdk/nashorn/internal/codegen/Lower.java	Wed Apr 23 16:13:47 2014 +0200
+++ b/nashorn/src/jdk/nashorn/internal/codegen/Lower.java	Wed Apr 23 17:37:41 2014 +0200
@@ -68,10 +68,10 @@
 import jdk.nashorn.internal.ir.WithNode;
 import jdk.nashorn.internal.ir.visitor.NodeOperatorVisitor;
 import jdk.nashorn.internal.ir.visitor.NodeVisitor;
-import jdk.nashorn.internal.objects.Global;
 import jdk.nashorn.internal.parser.Token;
 import jdk.nashorn.internal.parser.TokenType;
 import jdk.nashorn.internal.runtime.CodeInstaller;
+import jdk.nashorn.internal.runtime.Context;
 import jdk.nashorn.internal.runtime.ScriptRuntime;
 import jdk.nashorn.internal.runtime.Source;
 import jdk.nashorn.internal.runtime.logging.DebugLogger;
@@ -98,7 +98,7 @@
     /**
      * Constructor.
      */
-    Lower(final CodeInstaller<?> installer) {
+    Lower(final Compiler compiler) {
         super(new BlockLexicalContext() {
 
             @Override
@@ -142,8 +142,8 @@
             }
         });
 
-        this.installer = installer;
-        this.log = initLogger(Global.instance());
+        this.installer = compiler.getCodeInstaller();
+        this.log       = initLogger(compiler.getCompilationEnvironment().getContext());
     }
 
     @Override
@@ -152,8 +152,8 @@
     }
 
     @Override
-    public DebugLogger initLogger(final Global global) {
-        return global.getLogger(this.getClass());
+    public DebugLogger initLogger(final Context context) {
+        return context.getLogger(this.getClass());
     }
 
     @Override
--- a/nashorn/src/jdk/nashorn/internal/codegen/MethodEmitter.java	Wed Apr 23 16:13:47 2014 +0200
+++ b/nashorn/src/jdk/nashorn/internal/codegen/MethodEmitter.java	Wed Apr 23 17:37:41 2014 +0200
@@ -97,10 +97,10 @@
 import jdk.nashorn.internal.ir.Symbol;
 import jdk.nashorn.internal.objects.Global;
 import jdk.nashorn.internal.runtime.ArgumentSetter;
+import jdk.nashorn.internal.runtime.Context;
 import jdk.nashorn.internal.runtime.Debug;
 import jdk.nashorn.internal.runtime.JSType;
 import jdk.nashorn.internal.runtime.RewriteException;
-import jdk.nashorn.internal.runtime.ScriptEnvironment;
 import jdk.nashorn.internal.runtime.ScriptObject;
 import jdk.nashorn.internal.runtime.linker.Bootstrap;
 import jdk.nashorn.internal.runtime.logging.DebugLogger;
@@ -135,8 +135,8 @@
     /** Check whether this emitter ever has a function return point */
     private boolean hasReturn;
 
-    /** The script environment */
-    private final ScriptEnvironment env;
+    /** The context */
+    private final Context context;
 
     private final List<Type> localVariableTypes = new ArrayList<>();
 
@@ -144,8 +144,8 @@
     static final int LARGE_STRING_THRESHOLD = 32 * 1024;
 
     /** Debug flag, should we dump all generated bytecode along with stacks? */
-    private final DebugLogger log   = Global.instance().getLogger(CodeGenerator.class);
-    private final boolean     debug = log.isEnabled();
+    private final DebugLogger log;
+    private final boolean     debug;
 
     /** dump stack on a particular line, or -1 if disabled */
     private static final int DEBUG_TRACE_LINE;
@@ -193,11 +193,13 @@
      * @param functionNode a function node representing this method
      */
     MethodEmitter(final ClassEmitter classEmitter, final MethodVisitor method, final FunctionNode functionNode) {
-        this.env          = classEmitter.getEnv();
+        this.context      = classEmitter.getContext();
         this.classEmitter = classEmitter;
         this.method       = method;
         this.functionNode = functionNode;
         this.stack        = null;
+        this.log          = context.getLogger(CodeGenerator.class);
+        this.debug        = log.isEnabled();
     }
 
     /**
@@ -2226,7 +2228,7 @@
      * @param label label
      */
     void lineNumber(final int line) {
-        if (env._debug_lines) {
+        if (context.getEnv()._debug_lines) {
             debug_label("[LINE]", line);
             final jdk.internal.org.objectweb.asm.Label l = new jdk.internal.org.objectweb.asm.Label();
             method.visitLabel(l);
@@ -2385,7 +2387,7 @@
                 sb.append(' ');
             }
 
-            if (env != null) { //early bootstrap code doesn't have inited context yet
+            if (context.getEnv() != null) { //early bootstrap code doesn't have inited context yet
                 log.info(sb);
                 if (DEBUG_TRACE_LINE == linePrefix) {
                     new Throwable().printStackTrace(log.getOutputStream());
--- a/nashorn/src/jdk/nashorn/internal/codegen/ObjectClassGenerator.java	Wed Apr 23 16:13:47 2014 +0200
+++ b/nashorn/src/jdk/nashorn/internal/codegen/ObjectClassGenerator.java	Wed Apr 23 17:37:41 2014 +0200
@@ -55,7 +55,6 @@
 import java.util.List;
 import jdk.nashorn.internal.codegen.ClassEmitter.Flag;
 import jdk.nashorn.internal.codegen.types.Type;
-import jdk.nashorn.internal.objects.Global;
 import jdk.nashorn.internal.runtime.AccessorProperty;
 import jdk.nashorn.internal.runtime.Context;
 import jdk.nashorn.internal.runtime.FunctionScope;
@@ -147,13 +146,11 @@
     public ObjectClassGenerator(final Context context) {
         this.context = context;
         assert context != null;
-        this.log = initLogger(Global.instance());
-        synchronized (ObjectClassGenerator.class) {
-            if (!initialized) {
-                initialized = true;
-                if (OBJECT_FIELDS_ONLY) {
-                    log.warning("Running with object fields only - this is a deprecated configuration.");
-                }
+        this.log = initLogger(context);
+        if (!initialized) {
+            initialized = true;
+            if (OBJECT_FIELDS_ONLY) {
+                log.warning("Running with object fields only - this is a deprecated configuration.");
             }
         }
     }
@@ -164,8 +161,8 @@
     }
 
     @Override
-    public DebugLogger initLogger(final Global global) {
-        return global.getLogger(this.getClass());
+    public DebugLogger initLogger(final Context ctxt) {
+        return ctxt.getLogger(this.getClass());
     }
 
     /**
@@ -386,7 +383,7 @@
      * @return Open class emitter.
      */
     private ClassEmitter newClassEmitter(final String className, final String superName) {
-        final ClassEmitter classEmitter = new ClassEmitter(context.getEnv(), className, superName);
+        final ClassEmitter classEmitter = new ClassEmitter(context, className, superName);
         classEmitter.begin();
 
         return classEmitter;
--- a/nashorn/src/jdk/nashorn/internal/codegen/RangeAnalyzer.java	Wed Apr 23 16:13:47 2014 +0200
+++ b/nashorn/src/jdk/nashorn/internal/codegen/RangeAnalyzer.java	Wed Apr 23 17:37:41 2014 +0200
@@ -47,8 +47,8 @@
 import jdk.nashorn.internal.ir.VarNode;
 import jdk.nashorn.internal.ir.visitor.NodeOperatorVisitor;
 import jdk.nashorn.internal.ir.visitor.NodeVisitor;
-import jdk.nashorn.internal.objects.Global;
 import jdk.nashorn.internal.parser.TokenType;
+import jdk.nashorn.internal.runtime.Context;
 import jdk.nashorn.internal.runtime.logging.DebugLogger;
 import jdk.nashorn.internal.runtime.logging.Loggable;
 import jdk.nashorn.internal.runtime.logging.Logger;
@@ -74,9 +74,9 @@
 
     private final Map<LoopNode, Symbol> loopCounters = new HashMap<>();
 
-    RangeAnalyzer() {
+    RangeAnalyzer(final CompilationEnvironment env) {
         super(new LexicalContext());
-        this.log  = initLogger(Global.instance());
+        this.log  = initLogger(env.getContext());
         this.func = new Range.Functionality(log);
     }
 
@@ -86,8 +86,8 @@
     }
 
     @Override
-    public DebugLogger initLogger(final Global global) {
-        return global.getLogger(this.getClass());
+    public DebugLogger initLogger(final Context context) {
+        return context.getLogger(this.getClass());
     }
 
     @Override
--- a/nashorn/src/jdk/nashorn/internal/ir/debug/JSONWriter.java	Wed Apr 23 16:13:47 2014 +0200
+++ b/nashorn/src/jdk/nashorn/internal/ir/debug/JSONWriter.java	Wed Apr 23 17:37:41 2014 +0200
@@ -70,7 +70,6 @@
 import jdk.nashorn.internal.parser.TokenType;
 import jdk.nashorn.internal.runtime.Context;
 import jdk.nashorn.internal.runtime.ParserException;
-import jdk.nashorn.internal.runtime.ScriptEnvironment;
 import jdk.nashorn.internal.runtime.Source;
 
 /**
@@ -81,14 +80,14 @@
     /**
      * Returns AST as JSON compatible string.
      *
-     * @param env  script environment to use
+     * @param context context
      * @param code code to be parsed
      * @param name name of the code source (used for location)
      * @param includeLoc tells whether to include location information for nodes or not
      * @return JSON string representation of AST of the supplied code
      */
-    public static String parse(final ScriptEnvironment env, final String code, final String name, final boolean includeLoc) {
-        final Parser       parser     = new Parser(env, new Source(name, code), new Context.ThrowErrorManager(), env._strict);
+    public static String parse(final Context context, final String code, final String name, final boolean includeLoc) {
+        final Parser       parser     = new Parser(context.getEnv(), new Source(name, code), new Context.ThrowErrorManager(), context.getEnv()._strict, context.getLogger(Parser.class));
         final JSONWriter   jsonWriter = new JSONWriter(includeLoc);
         try {
             final FunctionNode functionNode = parser.parse(CompilerConstants.PROGRAM.symbolName());
@@ -317,7 +316,7 @@
     }
 
     @Override
-    public boolean enterBlockStatement(BlockStatement blockStatement) {
+    public boolean enterBlockStatement(final BlockStatement blockStatement) {
         enterDefault(blockStatement);
 
         type("BlockStatement");
@@ -337,13 +336,13 @@
             type("ForInStatement");
             comma();
 
-            Node init = forNode.getInit();
+            final Node init = forNode.getInit();
             assert init != null;
             property("left");
             init.accept(this);
             comma();
 
-            Node modify = forNode.getModify();
+            final Node modify = forNode.getModify();
             assert modify != null;
             property("right");
             modify.accept(this);
@@ -760,8 +759,8 @@
         final List<CatchNode> guarded = new ArrayList<>();
         CatchNode unguarded = null;
         if (catches != null) {
-            for (Node n : catches) {
-                CatchNode cn = (CatchNode)n;
+            for (final Node n : catches) {
+                final CatchNode cn = (CatchNode)n;
                 if (cn.getExceptionCondition() != null) {
                     guarded.add(cn);
                 } else {
@@ -957,9 +956,13 @@
         buf.append(key);
         buf.append("\":");
         if (value != null) {
-            if (escape) buf.append('"');
+            if (escape) {
+                buf.append('"');
+            }
             buf.append(value);
-            if (escape) buf.append('"');
+            if (escape) {
+                buf.append('"');
+            }
         }
     }
 
--- a/nashorn/src/jdk/nashorn/internal/lookup/MethodHandleFactory.java	Wed Apr 23 16:13:47 2014 +0200
+++ b/nashorn/src/jdk/nashorn/internal/lookup/MethodHandleFactory.java	Wed Apr 23 17:37:41 2014 +0200
@@ -37,8 +37,8 @@
 import java.util.List;
 import java.util.logging.Level;
 
-import jdk.nashorn.internal.objects.Global;
 import jdk.nashorn.internal.runtime.ConsString;
+import jdk.nashorn.internal.runtime.Context;
 import jdk.nashorn.internal.runtime.Debug;
 import jdk.nashorn.internal.runtime.logging.DebugLogger;
 import jdk.nashorn.internal.runtime.logging.Loggable;
@@ -107,7 +107,7 @@
      * Return the method handle functionality used for all method handle operations
      * @return a method handle functionality implementation
      */
-    public static synchronized MethodHandleFunctionality getFunctionality() {
+    public static MethodHandleFunctionality getFunctionality() {
         return FUNC;
     }
 
@@ -286,8 +286,8 @@
         }
 
         @Override
-        public DebugLogger initLogger(final Global global) {
-            return this.log = global.getLogger(this.getClass());
+        public DebugLogger initLogger(final Context context) {
+            return this.log = context.getLogger(this.getClass());
         }
 
         @Override
--- a/nashorn/src/jdk/nashorn/internal/objects/Global.java	Wed Apr 23 16:13:47 2014 +0200
+++ b/nashorn/src/jdk/nashorn/internal/objects/Global.java	Wed Apr 23 17:37:41 2014 +0200
@@ -44,15 +44,13 @@
 import java.util.Map;
 import java.util.concurrent.Callable;
 import java.util.concurrent.ConcurrentHashMap;
-import java.util.function.Supplier;
-import java.util.logging.Level;
+import java.util.concurrent.atomic.AtomicReference;
 
 import jdk.internal.dynalink.linker.GuardedInvocation;
 import jdk.internal.dynalink.linker.LinkRequest;
 import jdk.nashorn.internal.codegen.ApplySpecialization;
 import jdk.nashorn.internal.codegen.CompilerConstants.Call;
 import jdk.nashorn.internal.lookup.Lookup;
-import jdk.nashorn.internal.lookup.MethodHandleFactory;
 import jdk.nashorn.internal.objects.annotations.Attribute;
 import jdk.nashorn.internal.objects.annotations.Property;
 import jdk.nashorn.internal.objects.annotations.ScriptClass;
@@ -73,11 +71,7 @@
 import jdk.nashorn.internal.runtime.arrays.ArrayData;
 import jdk.nashorn.internal.runtime.linker.Bootstrap;
 import jdk.nashorn.internal.runtime.linker.InvokeByName;
-import jdk.nashorn.internal.runtime.options.LoggingOption.LoggerInfo;
 import jdk.nashorn.internal.runtime.regexp.RegExpResult;
-import jdk.nashorn.internal.runtime.logging.DebugLogger;
-import jdk.nashorn.internal.runtime.logging.Logger;
-import jdk.nashorn.internal.runtime.logging.Loggable;
 import jdk.nashorn.internal.scripts.JO;
 
 /**
@@ -437,12 +431,8 @@
     // context to which this global belongs to
     private final Context context;
 
-    // logging
-    private final Map<String, DebugLogger> loggers = new HashMap<>();
-
-    private void initLoggers() {
-        ((Loggable)MethodHandleFactory.getFunctionality()).initLogger(this);
-    }
+    // global constants for this global - they can be replaced with MethodHandle.constant until invalidated
+    private static AtomicReference<GlobalConstants> gcsInstance = new AtomicReference<>();
 
     @Override
     protected Context getContext() {
@@ -479,8 +469,11 @@
         this.context = context;
         this.setIsScope();
         this.optimisticFunctionMap = new HashMap<>();
-        final GlobalConstants gc = GlobalConstants.instance(this);
-        gc.invalidateAll();
+        //we can only share one instance of Global constants between globals, or we consume way too much
+        //memory - this is good enough for most programs
+        while (gcsInstance.get() == null) {
+            gcsInstance.compareAndSet(null, new GlobalConstants(context.getLogger(GlobalConstants.class)));
+        }
     }
 
     /**
@@ -495,6 +488,15 @@
     }
 
     /**
+     * Return the global constants map for fields that
+     * can be accessed as MethodHandle.constant
+     * @return constant map
+     */
+    public static GlobalConstants getConstants() {
+        return gcsInstance.get();
+    }
+
+    /**
      * Check if we have a Global instance
      * @return true if one exists
      */
@@ -1714,8 +1716,6 @@
             // synonym for "arguments" in scripting mode
             addOwnProperty("$ARG", argumentsFlags, argumentsObject);
         }
-
-        initLoggers();
     }
 
     private void initErrorObjects() {
@@ -2097,7 +2097,7 @@
     public void invalidateReservedName(final String name) {
         final SwitchPoint sp = getChangeCallback(name);
         if (sp != null) {
-            getLogger(ApplySpecialization.class).info("Overwrote special name '" + name +"' - invalidating switchpoint");
+            getContext().getLogger(ApplySpecialization.class).info("Overwrote special name '" + name +"' - invalidating switchpoint");
             SwitchPoint.invalidateAll(new SwitchPoint[] { sp });
         }
     }
@@ -2114,72 +2114,5 @@
         return new ConstantCallSite(target);
     }
 
-    /**
-     * Get a logger, given a loggable class
-     * @param clazz a Loggable class
-     * @return debuglogger associated with that class
-     */
-    public DebugLogger getLogger(final Class<? extends Loggable> clazz) {
-        final String name = getLoggerName(clazz);
-        DebugLogger logger = loggers.get(name);
-        if (logger == null) {
-            final ScriptEnvironment env = context.getEnv();
-            if (!env.hasLogger(name)) {
-                return DebugLogger.DISABLED_LOGGER;
-            }
-            final LoggerInfo info = env._loggers.get(name);
-            logger = new DebugLogger(name, info.getLevel(), info.isQuiet());
-            loggers.put(name, logger);
-        }
-        return logger;
-    }
-
-    /**
-     * Given a Loggable class, weave debug info info a method handle for that logger.
-     * Level.INFO is used
-     *
-     * @param clazz loggable
-     * @param mh    method handle
-     * @param text  debug printout to add
-     *
-     * @return instrumented method handle, or null if logger not enabled
-     */
-    public MethodHandle addLoggingToHandle(final Class<? extends Loggable> clazz, final MethodHandle mh, final Supplier<String> text) {
-        return addLoggingToHandle(clazz, Level.INFO, mh, Integer.MAX_VALUE, false, text);
-    }
-
-    /**
-     * Given a Loggable class, weave debug info info a method handle for that logger.
-     *
-     * @param clazz            loggable
-     * @param level            log level
-     * @param mh               method handle
-     * @param paramStart       first parameter to print
-     * @param printReturnValue should we print the return vaulue?
-     * @param text             debug printout to add
-     *
-     * @return instrumented method handle, or null if logger not enabled
-     */
-    public MethodHandle addLoggingToHandle(final Class<? extends Loggable> clazz, final Level level, final MethodHandle mh, final int paramStart, final boolean printReturnValue, final Supplier<String> text) {
-        final DebugLogger log = getLogger(clazz);
-        if (log.isEnabled()) {
-            return MethodHandleFactory.addDebugPrintout(log, level, mh, paramStart, printReturnValue, text.get());
-        }
-        return mh;
-    }
-
-    private static String getLoggerName(final Class<?> clazz) {
-        Class<?> current = clazz;
-        while (current != null) {
-            final Logger log = current.getAnnotation(Logger.class);
-            if (log != null) {
-                assert !"".equals(log.name());
-                return log.name();
-            }
-            current = current.getSuperclass();
-        }
-        assert false;
-        return null;
-    }
 
 }
--- a/nashorn/src/jdk/nashorn/internal/objects/NativeFunction.java	Wed Apr 23 16:13:47 2014 +0200
+++ b/nashorn/src/jdk/nashorn/internal/objects/NativeFunction.java	Wed Apr 23 17:37:41 2014 +0200
@@ -289,7 +289,7 @@
     private static void checkFunctionParameters(final String params) {
         final Source            src    = new Source("<function>", params);
         final ScriptEnvironment env    = Global.getEnv();
-        final Parser            parser = new Parser(env, src, new Context.ThrowErrorManager(), env._strict);
+        final Parser            parser = new Parser(env, src, new Context.ThrowErrorManager(), env._strict, null);
         try {
             parser.parseFormalParameterList();
         } catch (final ParserException pe) {
@@ -300,7 +300,7 @@
     private static void checkFunctionBody(final String funcBody) {
         final Source            src    = new Source("<function>", funcBody);
         final ScriptEnvironment env    = Global.getEnv();
-        final Parser            parser = new Parser(env, src, new Context.ThrowErrorManager(), env._strict);
+        final Parser            parser = new Parser(env, src, new Context.ThrowErrorManager(), env._strict, null);
         try {
             parser.parseFunctionBody();
         } catch (final ParserException pe) {
--- a/nashorn/src/jdk/nashorn/internal/parser/Parser.java	Wed Apr 23 16:13:47 2014 +0200
+++ b/nashorn/src/jdk/nashorn/internal/parser/Parser.java	Wed Apr 23 17:37:41 2014 +0200
@@ -105,7 +105,7 @@
 import jdk.nashorn.internal.ir.VarNode;
 import jdk.nashorn.internal.ir.WhileNode;
 import jdk.nashorn.internal.ir.WithNode;
-import jdk.nashorn.internal.objects.Global;
+import jdk.nashorn.internal.runtime.Context;
 import jdk.nashorn.internal.runtime.ErrorManager;
 import jdk.nashorn.internal.runtime.JSErrorType;
 import jdk.nashorn.internal.runtime.ParserException;
@@ -125,7 +125,7 @@
 public class Parser extends AbstractParser implements Loggable {
     private static final String ARGUMENTS_NAME = CompilerConstants.ARGUMENTS_VAR.symbolName();
 
-    /** Current script environment. */
+    /** Current env. */
     private final ScriptEnvironment env;
 
     /** Is scripting mode. */
@@ -154,7 +154,7 @@
      * @param errors  error manager
      */
     public Parser(final ScriptEnvironment env, final Source source, final ErrorManager errors) {
-        this(env, source, errors, env._strict);
+        this(env, source, errors, env._strict, null);
     }
 
     /**
@@ -164,9 +164,10 @@
      * @param source  source to parse
      * @param errors  error manager
      * @param strict  strict
+     * @param log debug logger if one is needed
      */
-    public Parser(final ScriptEnvironment env, final Source source, final ErrorManager errors, final boolean strict) {
-        this(env, source, errors, strict, FunctionNode.FIRST_FUNCTION_ID, 0);
+    public Parser(final ScriptEnvironment env, final Source source, final ErrorManager errors, final boolean strict, final DebugLogger log) {
+        this(env, source, errors, strict, FunctionNode.FIRST_FUNCTION_ID, 0, log);
     }
 
     /**
@@ -178,10 +179,11 @@
      * @param strict  parser created with strict mode enabled.
      * @param nextFunctionId  starting value for assigning new unique ids to function nodes
      * @param lineOffset line offset to start counting lines from
+     * @param log debug logger if one is needed
      */
-    public Parser(final ScriptEnvironment env, final Source source, final ErrorManager errors, final boolean strict, final int nextFunctionId, final int lineOffset) {
+    public Parser(final ScriptEnvironment env, final Source source, final ErrorManager errors, final boolean strict, final int nextFunctionId, final int lineOffset, final DebugLogger log) {
         super(source, errors, strict, lineOffset);
-        this.env        = env;
+        this.env = env;
         this.namespace = new Namespace(env.getNamespace());
         this.nextFunctionId    = nextFunctionId;
         this.scripting = env._scripting;
@@ -199,7 +201,7 @@
             this.lineInfoReceiver = null;
         }
 
-        this.log = !Global.hasInstance() ? DebugLogger.DISABLED_LOGGER : initLogger(Global.instance());
+        this.log = log == null ? DebugLogger.DISABLED_LOGGER : log;
     }
 
     @Override
@@ -208,8 +210,8 @@
     }
 
     @Override
-    public DebugLogger initLogger(final Global global) {
-        return global.getLogger(this.getClass());
+    public DebugLogger initLogger(final Context context) {
+        return context.getLogger(this.getClass());
     }
 
     /**
--- a/nashorn/src/jdk/nashorn/internal/runtime/AccessorProperty.java	Wed Apr 23 16:13:47 2014 +0200
+++ b/nashorn/src/jdk/nashorn/internal/runtime/AccessorProperty.java	Wed Apr 23 17:37:41 2014 +0200
@@ -691,69 +691,77 @@
 
 
     private MethodHandle debug(final MethodHandle mh, final Class<?> forType, final Class<?> type, final String tag) {
-        if (Global.hasInstance()) {
-            return Global.instance().addLoggingToHandle(
-                    ObjectClassGenerator.class,
-                    Level.INFO,
-                    mh,
-                    0,
-                    true,
-                    new Supplier<String>() {
-                        @Override
-                        public String get() {
-                            return tag + " '" + getKey() + "' (property="+ Debug.id(this) + ", slot=" + getSlot() + " " + getClass().getSimpleName() + " forType=" + stripName(forType) + ", type=" + stripName(type) + ')';
-                        }
-                    });
+        if (!Global.hasInstance()) {
+            return mh;
         }
 
+        final Context context = Context.getContextTrusted();
+        assert context != null;
+
+        return context.addLoggingToHandle(
+                ObjectClassGenerator.class,
+                Level.INFO,
+                mh,
+                0,
+                true,
+                new Supplier<String>() {
+                    @Override
+                    public String get() {
+                        return tag + " '" + getKey() + "' (property="+ Debug.id(this) + ", slot=" + getSlot() + " " + getClass().getSimpleName() + " forType=" + stripName(forType) + ", type=" + stripName(type) + ')';
+                    }
+                });
+    }
+
+    private MethodHandle debugReplace(final Class<?> oldType, final Class<?> newType, final PropertyMap oldMap, final PropertyMap newMap) {
+        if (!Global.hasInstance()) {
+            return REPLACE_MAP;
+        }
+
+        final Context context = Context.getContextTrusted();
+        assert context != null;
+
+        MethodHandle mh = context.addLoggingToHandle(
+                ObjectClassGenerator.class,
+                REPLACE_MAP,
+                new Supplier<String>() {
+                    @Override
+                    public String get() {
+                        return "Type change for '" + getKey() + "' " + oldType + "=>" + newType;
+                    }
+                });
+
+        mh = context.addLoggingToHandle(
+                ObjectClassGenerator.class,
+                Level.FINEST,
+                mh,
+                Integer.MAX_VALUE,
+                false,
+                new Supplier<String>() {
+                    @Override
+                    public String get() {
+                        return "Setting map " + Debug.id(oldMap) + " => " + Debug.id(newMap) + " " + oldMap + " => " + newMap;
+                    }
+                });
         return mh;
     }
 
-    private MethodHandle debugReplace(final Class<?> oldType, final Class<?> newType, final PropertyMap oldMap, final PropertyMap newMap) {
-        if (Global.hasInstance()) {
-            final Global global = Global.instance();
-            MethodHandle mh = global.addLoggingToHandle(
-                    ObjectClassGenerator.class,
-                    REPLACE_MAP,
-                    new Supplier<String>() {
-                        @Override
-                        public String get() {
-                            return "Type change for '" + getKey() + "' " + oldType + "=>" + newType;
-                        }
-                    });
-
-            mh = global.addLoggingToHandle(
-                    ObjectClassGenerator.class,
-                    Level.FINEST,
-                    mh,
-                    Integer.MAX_VALUE,
-                    false,
-                    new Supplier<String>() {
-                        @Override
-                        public String get() {
-                            return "Setting map " + Debug.id(oldMap) + " => " + Debug.id(newMap) + " " + oldMap + " => " + newMap;
-                        }
-                    });
-            return mh;
+    private static MethodHandle debugInvalidate(final String key, final SwitchPoint sp) {
+        if (!Global.hasInstance()) {
+            return INVALIDATE_SP;
         }
 
-        return REPLACE_MAP;
-    }
+        final Context context = Context.getContextTrusted();
+        assert context != null;
 
-    private static MethodHandle debugInvalidate(final String key, final SwitchPoint sp) {
-        if (Global.hasInstance()) {
-            return Global.instance().addLoggingToHandle(
-                    ObjectClassGenerator.class,
-                    INVALIDATE_SP,
-                    new Supplier<String>() {
-                        @Override
-                        public String get() {
-                            return "Field change callback for " + key + " triggered: " + sp;
-                        }
-                    });
-        }
-
-        return INVALIDATE_SP;
+        return context.addLoggingToHandle(
+                ObjectClassGenerator.class,
+                INVALIDATE_SP,
+                new Supplier<String>() {
+                    @Override
+                    public String get() {
+                        return "Field change callback for " + key + " triggered: " + sp;
+                    }
+                });
     }
 
     private static MethodHandle findOwnMH_S(final String name, final Class<?> rtype, final Class<?>... types) {
--- a/nashorn/src/jdk/nashorn/internal/runtime/CompiledFunction.java	Wed Apr 23 16:13:47 2014 +0200
+++ b/nashorn/src/jdk/nashorn/internal/runtime/CompiledFunction.java	Wed Apr 23 17:37:41 2014 +0200
@@ -41,7 +41,6 @@
 import jdk.nashorn.internal.codegen.types.ArrayType;
 import jdk.nashorn.internal.codegen.types.Type;
 import jdk.nashorn.internal.ir.FunctionNode;
-import jdk.nashorn.internal.objects.Global;
 import jdk.nashorn.internal.runtime.events.RecompilationEvent;
 import jdk.nashorn.internal.runtime.linker.Bootstrap;
 import jdk.nashorn.internal.runtime.logging.DebugLogger;
@@ -72,22 +71,25 @@
     private boolean applyToCall;
 
     CompiledFunction(final MethodHandle invoker) {
-        this.invoker = invoker;
-        this.log = Global.instance().getLogger(RecompilableScriptFunctionData.class);
+        this(invoker, null);
     }
 
     static CompiledFunction createBuiltInConstructor(final MethodHandle invoker) {
-        return new CompiledFunction(MH.insertArguments(invoker, 0, false),
-                createConstructorFromInvoker(MH.insertArguments(invoker, 0, true)));
+        return new CompiledFunction(MH.insertArguments(invoker, 0, false), createConstructorFromInvoker(MH.insertArguments(invoker, 0, true)));
     }
 
     CompiledFunction(final MethodHandle invoker, final MethodHandle constructor) {
-        this(invoker);
+        this(invoker, constructor, DebugLogger.DISABLED_LOGGER);
+    }
+
+    CompiledFunction(final MethodHandle invoker, final MethodHandle constructor, final DebugLogger log) {
+        this.invoker = invoker;
         this.constructor = constructor;
+        this.log = log;
     }
 
     CompiledFunction(final MethodHandle invoker, final RecompilableScriptFunctionData functionData, final int flags) {
-        this(invoker);
+        this(invoker, null, functionData.getLogger());
         this.flags = flags;
         if ((flags & FunctionNode.IS_OPTIMISTIC) != 0) {
             optimismInfo = new OptimismInfo(functionData);
@@ -620,10 +622,11 @@
         private final RecompilableScriptFunctionData data;
         private final Map<Integer, Type> invalidatedProgramPoints = new TreeMap<>();
         private SwitchPoint optimisticAssumptions;
-        private final DebugLogger log = Global.instance().getLogger(RecompilableScriptFunctionData.class);
+        private final DebugLogger log;
 
         OptimismInfo(final RecompilableScriptFunctionData data) {
             this.data = data;
+            this.log  = data.getLogger();
             newOptimisticAssumptions();
         }
 
--- a/nashorn/src/jdk/nashorn/internal/runtime/Context.java	Wed Apr 23 16:13:47 2014 +0200
+++ b/nashorn/src/jdk/nashorn/internal/runtime/Context.java	Wed Apr 23 17:37:41 2014 +0200
@@ -33,6 +33,7 @@
 import java.io.File;
 import java.io.IOException;
 import java.io.PrintWriter;
+import java.lang.invoke.MethodHandle;
 import java.lang.ref.ReferenceQueue;
 import java.lang.ref.SoftReference;
 import java.lang.reflect.InvocationTargetException;
@@ -46,9 +47,11 @@
 import java.security.Permissions;
 import java.security.PrivilegedAction;
 import java.security.ProtectionDomain;
+import java.util.HashMap;
 import java.util.LinkedHashMap;
 import java.util.Map;
 import java.util.concurrent.atomic.AtomicLong;
+import java.util.function.Supplier;
 import java.util.logging.Level;
 
 import jdk.internal.org.objectweb.asm.ClassReader;
@@ -62,11 +65,15 @@
 import jdk.nashorn.internal.ir.FunctionNode;
 import jdk.nashorn.internal.ir.debug.ASTWriter;
 import jdk.nashorn.internal.ir.debug.PrintVisitor;
+import jdk.nashorn.internal.lookup.MethodHandleFactory;
 import jdk.nashorn.internal.objects.Global;
 import jdk.nashorn.internal.parser.Parser;
 import jdk.nashorn.internal.runtime.events.RuntimeEvent;
 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.Options;
+import jdk.nashorn.internal.runtime.options.LoggingOption.LoggerInfo;
 
 /**
  * This class manages the global state of execution. Context is immutable.
@@ -196,7 +203,9 @@
         // Trusted code only can call this method.
         assert getGlobal() != global;
         //same code can be cached between globals, then we need to invalidate method handle constants
-        GlobalConstants.instance(global).invalidateAll();
+        if (global != null) {
+            Global.getConstants().invalidateAll();
+        }
         currentGlobal.set(global);
     }
 
@@ -383,6 +392,8 @@
         if (env._fullversion) {
             getErr().println("nashorn full version " + Version.fullVersion());
         }
+
+        initLoggers();
     }
 
     /**
@@ -916,14 +927,14 @@
 
         Class<?> script = findCachedClass(source);
         if (script != null) {
-            final DebugLogger log = Global.instance().getLogger(Compiler.class);
+            final DebugLogger log = getLogger(Compiler.class);
             if (log.isEnabled()) {
                 log.fine(new RuntimeEvent<>(Level.INFO, source), "Code cache hit for ", source, " avoiding recompile.");
             }
             return script;
         }
 
-        final FunctionNode functionNode = new Parser(env, source, errMan, strict).parse();
+        final FunctionNode functionNode = new Parser(env, source, errMan, strict, getLogger(Parser.class)).parse();
         if (errors.hasErrors()) {
             return null;
         }
@@ -948,6 +959,7 @@
         final CompilationPhases phases = CompilationEnvironment.CompilationPhases.EAGER;
         final Compiler compiler = new Compiler(
                 new CompilationEnvironment(
+                    this,
                     phases.
                         makeOptimistic(
                             ScriptEnvironment.globalOptimistic()),
@@ -1032,4 +1044,79 @@
             classCache.cache(source, clazz);
         }
     }
+
+    // logging
+    private final Map<String, DebugLogger> loggers = new HashMap<>();
+
+    private void initLoggers() {
+        ((Loggable)MethodHandleFactory.getFunctionality()).initLogger(this);
+    }
+
+    /**
+     * Get a logger, given a loggable class
+     * @param clazz a Loggable class
+     * @return debuglogger associated with that class
+     */
+    public DebugLogger getLogger(final Class<? extends Loggable> clazz) {
+        final String name = getLoggerName(clazz);
+        DebugLogger logger = loggers.get(name);
+        if (logger == null) {
+            if (!env.hasLogger(name)) {
+                return DebugLogger.DISABLED_LOGGER;
+            }
+            final LoggerInfo info = env._loggers.get(name);
+            logger = new DebugLogger(name, info.getLevel(), info.isQuiet());
+            loggers.put(name, logger);
+        }
+        return logger;
+    }
+
+    /**
+     * Given a Loggable class, weave debug info info a method handle for that logger.
+     * Level.INFO is used
+     *
+     * @param clazz loggable
+     * @param mh    method handle
+     * @param text  debug printout to add
+     *
+     * @return instrumented method handle, or null if logger not enabled
+     */
+    public MethodHandle addLoggingToHandle(final Class<? extends Loggable> clazz, final MethodHandle mh, final Supplier<String> text) {
+        return addLoggingToHandle(clazz, Level.INFO, mh, Integer.MAX_VALUE, false, text);
+    }
+
+    /**
+     * Given a Loggable class, weave debug info info a method handle for that logger.
+     *
+     * @param clazz            loggable
+     * @param level            log level
+     * @param mh               method handle
+     * @param paramStart       first parameter to print
+     * @param printReturnValue should we print the return vaulue?
+     * @param text             debug printout to add
+     *
+     * @return instrumented method handle, or null if logger not enabled
+     */
+    public MethodHandle addLoggingToHandle(final Class<? extends Loggable> clazz, final Level level, final MethodHandle mh, final int paramStart, final boolean printReturnValue, final Supplier<String> text) {
+        final DebugLogger log = getLogger(clazz);
+        if (log.isEnabled()) {
+            return MethodHandleFactory.addDebugPrintout(log, level, mh, paramStart, printReturnValue, text.get());
+        }
+        return mh;
+    }
+
+    private static String getLoggerName(final Class<?> clazz) {
+        Class<?> current = clazz;
+        while (current != null) {
+            final Logger log = current.getAnnotation(Logger.class);
+            if (log != null) {
+                assert !"".equals(log.name());
+                return log.name();
+            }
+            current = current.getSuperclass();
+        }
+        assert false;
+        return null;
+    }
+
 }
--- a/nashorn/src/jdk/nashorn/internal/runtime/GlobalConstants.java	Wed Apr 23 16:13:47 2014 +0200
+++ b/nashorn/src/jdk/nashorn/internal/runtime/GlobalConstants.java	Wed Apr 23 17:37:41 2014 +0200
@@ -44,7 +44,6 @@
 import jdk.internal.dynalink.linker.LinkRequest;
 import jdk.nashorn.internal.lookup.Lookup;
 import jdk.nashorn.internal.lookup.MethodHandleFactory;
-import jdk.nashorn.internal.objects.Global;
 import jdk.nashorn.internal.runtime.linker.NashornCallSiteDescriptor;
 import jdk.nashorn.internal.runtime.logging.DebugLogger;
 import jdk.nashorn.internal.runtime.logging.Loggable;
@@ -71,11 +70,12 @@
  * We can extend this to ScriptObjects in general (GLOBAL_ONLY=false), which requires
  * a receiver guard on the constant getter, but it currently leaks memory and its benefits
  * have not yet been investigated property.
+ *
+ * As long as all Globals share the same constant instance, we need synchronization
+ * whenever we access the instance.
  */
 @Logger(name="const")
 public final class GlobalConstants implements Loggable {
-    /** singleton per global */
-    private static GlobalConstants instance;
 
     /**
      * Should we only try to link globals as constants, and not generic script objects.
@@ -98,8 +98,12 @@
      */
     private final Map<String, Access> map = new HashMap<>();
 
-    private GlobalConstants(final Global global) {
-        this.log = initLogger(global);
+    /**
+     * Constructor - used only by global
+     * @param log logger, or null if none
+     */
+    public GlobalConstants(final DebugLogger log) {
+        this.log = log == null ? DebugLogger.DISABLED_LOGGER : log;
     }
 
     @Override
@@ -108,20 +112,8 @@
     }
 
     @Override
-    public DebugLogger initLogger(final Global global) {
-        return global.getLogger(this.getClass());
-    }
-
-    /**
-     * Return the singleton global constant pool
-     * @param global global
-     * @return singleton global constant pool
-     */
-    public static synchronized GlobalConstants instance(final Global global) {
-        if (instance == null) {
-            instance = new GlobalConstants(global);
-        }
-        return instance;
+    public DebugLogger initLogger(final Context context) {
+        return DebugLogger.DISABLED_LOGGER;
     }
 
     /**
@@ -224,7 +216,7 @@
      * the same class for a new global, but the builtins and global scoped variables
      * will have changed.
      */
-    public void invalidateAll() {
+    public synchronized void invalidateAll() {
         log.info("New global created - invalidating all constant callsites without increasing invocation count.");
         for (final Access acc : map.values()) {
             acc.invalidateUncounted();
@@ -241,7 +233,7 @@
      * @return receiver, so this can be used as param filter
      */
     @SuppressWarnings("unused")
-    private Object invalidateSwitchPoint(final Object obj, final Access acc) {
+    private synchronized Object invalidateSwitchPoint(final Object obj, final Access acc) {
         if (log.isEnabled()) {
             log.info("*** Invalidating switchpoint " + acc.getSwitchPoint() + " for receiver=" + obj + " access=" + acc);
         }
@@ -259,7 +251,7 @@
         return obj;
     }
 
-    private Access getOrCreateSwitchPoint(final String name) {
+    private synchronized Access getOrCreateSwitchPoint(final String name) {
         Access acc = map.get(name);
         if (acc != null) {
             return acc;
@@ -321,7 +313,7 @@
      *
      * @return null if failed to set up constant linkage
      */
-    GuardedInvocation findSetMethod(final FindProperty find, final ScriptObject receiver, final GuardedInvocation inv, final CallSiteDescriptor desc, final LinkRequest request) {
+    synchronized GuardedInvocation findSetMethod(final FindProperty find, final ScriptObject receiver, final GuardedInvocation inv, final CallSiteDescriptor desc, final LinkRequest request) {
         if (GLOBAL_ONLY && !isGlobalSetter(receiver, find)) {
             return null;
         }
@@ -365,8 +357,12 @@
      * @param c constant value
      * @return method handle (with dummy receiver) that returns this constant
      */
-    private static MethodHandle constantGetter(final Object c) {
-        return MH.dropArguments(JSType.unboxConstant(c), 0, Object.class);
+    private MethodHandle constantGetter(final Object c) {
+        final MethodHandle mh = MH.dropArguments(JSType.unboxConstant(c), 0, Object.class);
+        if (log.isEnabled()) {
+            return MethodHandleFactory.addDebugPrintout(log, Level.FINEST, mh, "getting as constant");
+        }
+        return mh;
     }
 
     /**
@@ -380,7 +376,7 @@
      *
      * @return resulting getter, or null if failed to create constant
      */
-    GuardedInvocation findGetMethod(final FindProperty find, final ScriptObject receiver, final CallSiteDescriptor desc, final LinkRequest request, final String operator) {
+    synchronized GuardedInvocation findGetMethod(final FindProperty find, final ScriptObject receiver, final CallSiteDescriptor desc, final LinkRequest request, final String operator) {
         if (GLOBAL_ONLY && !find.getOwner().isGlobal()) {
             return null;
         }
--- a/nashorn/src/jdk/nashorn/internal/runtime/RecompilableScriptFunctionData.java	Wed Apr 23 16:13:47 2014 +0200
+++ b/nashorn/src/jdk/nashorn/internal/runtime/RecompilableScriptFunctionData.java	Wed Apr 23 17:37:41 2014 +0200
@@ -50,7 +50,6 @@
 import jdk.nashorn.internal.ir.FunctionNode;
 import jdk.nashorn.internal.ir.LexicalContext;
 import jdk.nashorn.internal.ir.visitor.NodeVisitor;
-import jdk.nashorn.internal.objects.Global;
 import jdk.nashorn.internal.parser.Parser;
 import jdk.nashorn.internal.parser.Token;
 import jdk.nashorn.internal.parser.TokenType;
@@ -123,11 +122,14 @@
 
     private final Set<String> internalSymbols;
 
+    private final Context context;
+
     private static final int GET_SET_PREFIX_LENGTH = "*et ".length();
 
     /**
      * Constructor - public as scripts use it
      *
+     * @param context             context
      * @param functionNode        functionNode that represents this function code
      * @param installer           installer for code regeneration versions of this function
      * @param allocatorClassName  name of our allocator class, will be looked up dynamically if used as a constructor
@@ -138,6 +140,7 @@
      * @param internalSymbols     internal symbols to method, defined in its scope
      */
     public RecompilableScriptFunctionData(
+        final Context context,
         final FunctionNode functionNode,
         final CodeInstaller<ScriptEnvironment> installer,
         final String allocatorClassName,
@@ -151,6 +154,7 @@
               Math.min(functionNode.getParameters().size(), MAX_ARITY),
               getFlags(functionNode));
 
+        this.context             = context;
         this.functionName        = functionNode.getName();
         this.lineNumber          = functionNode.getLineNumber();
         this.isDeclared          = functionNode.isDeclared();
@@ -172,7 +176,7 @@
             nfn.setParent(this);
         }
 
-        this.log = initLogger(Global.instance());
+        this.log = initLogger(context);
     }
 
     @Override
@@ -181,8 +185,8 @@
     }
 
     @Override
-    public DebugLogger initLogger(final Global global) {
-        return global.getLogger(this.getClass());
+    public DebugLogger initLogger(final Context ctxt) {
+        return ctxt.getLogger(this.getClass());
     }
 
     /**
@@ -331,12 +335,13 @@
         // NOTE: If we aren't recompiling the top-level program, we decrease functionNodeId 'cause we'll have a synthetic program node
         final int descPosition = Token.descPosition(token);
         final Parser parser = new Parser(
-            installer.getOwner(),
+            context.getEnv(),
             source,
             new Context.ThrowErrorManager(),
             isStrict(),
             functionNodeId - (isProgram ? 0 : 1),
-            lineNumber - 1); // source starts at line 0, so even though lineNumber is the correct declaration line, back off one to make it exclusive
+            lineNumber - 1,
+            context.getLogger(Parser.class)); // source starts at line 0, so even though lineNumber is the correct declaration line, back off one to make it exclusive
 
         if (isAnonymous) {
             parser.setFunctionName(functionName);
@@ -420,6 +425,7 @@
 
         final Compiler compiler = new Compiler(
                 new CompilationEnvironment(
+                    context,
                     CompilationPhases.EAGER.makeOptimistic(),
                     isStrict(),
                     this,
@@ -454,13 +460,14 @@
         final CompilationPhases phases = CompilationPhases.EAGER;
         final Compiler compiler = new Compiler(
             new CompilationEnvironment(
-                phases.makeOptimistic(ScriptEnvironment.globalOptimistic()),
-                isStrict(),
-                this,
-                runtimeScope,
-                ptm,
-                invalidatedProgramPoints,
-                true),
+                    context,
+                    phases.makeOptimistic(ScriptEnvironment.globalOptimistic()),
+                    isStrict(),
+                    this,
+                    runtimeScope,
+                    ptm,
+                    invalidatedProgramPoints,
+                    true),
             installer);
 
         fn = compiler.compile(scriptName, fn);
@@ -744,7 +751,7 @@
         public FunctionNode apply(final FunctionNode functionNode) {
             this.initialFunctionNode = functionNode;
             if (data.isVariableArity()) {
-                final ApplySpecialization spec = new ApplySpecialization(data, functionNode, actualCallSiteType);
+                final ApplySpecialization spec = new ApplySpecialization(data.context, data, functionNode, actualCallSiteType);
                 if (spec.transform()) {
                     setTransformedFunctionNode(spec.getFunctionNode());
                     return transformedFunctionNode;
--- a/nashorn/src/jdk/nashorn/internal/runtime/ScriptFunction.java	Wed Apr 23 16:13:47 2014 +0200
+++ b/nashorn/src/jdk/nashorn/internal/runtime/ScriptFunction.java	Wed Apr 23 17:37:41 2014 +0200
@@ -681,7 +681,7 @@
         if (isApplyToCall) {
             if (isFailedApplyToCall) {
                 //take the real arguments that were passed to a call and force them into the apply instead
-                Global.instance().getLogger(ApplySpecialization.class).info("Collection arguments to revert call to apply in " + appliedFn);
+                Context.getContextTrusted().getLogger(ApplySpecialization.class).info("Collection arguments to revert call to apply in " + appliedFn);
                 inv = MH.asCollector(inv, Object[].class, realArgCount);
             } else {
                 appliedInvocation = appliedInvocation.addSwitchPoint(applyToCallSwitchPoint);
--- a/nashorn/src/jdk/nashorn/internal/runtime/ScriptObject.java	Wed Apr 23 16:13:47 2014 +0200
+++ b/nashorn/src/jdk/nashorn/internal/runtime/ScriptObject.java	Wed Apr 23 17:37:41 2014 +0200
@@ -918,7 +918,7 @@
                 if (property instanceof UserAccessorProperty) {
                     ((UserAccessorProperty)property).setAccessors(this, getMap(), null);
                 }
-                GlobalConstants.instance(Global.instance()).delete(property.getKey());
+                Global.getConstants().delete(property.getKey());
                 return true;
             }
         }
@@ -1930,7 +1930,7 @@
             }
         }
 
-        final GuardedInvocation cinv = GlobalConstants.instance(Global.instance()).findGetMethod(find, this, desc, request, operator);
+        final GuardedInvocation cinv = Global.getConstants().findGetMethod(find, this, desc, request, operator);
         if (cinv != null) {
             return cinv;
         }
@@ -1971,7 +1971,7 @@
     }
 
     private static GuardedInvocation findMegaMorphicGetMethod(final CallSiteDescriptor desc, final String name, final boolean isMethod, final boolean isScope) {
-        Global.instance().getLogger(ObjectClassGenerator.class).warning("Megamorphic getter: " + desc + " " + name + " " +isMethod);
+        Context.getContextTrusted().getLogger(ObjectClassGenerator.class).warning("Megamorphic getter: " + desc + " " + name + " " +isMethod);
         final MethodHandle invoker = MH.insertArguments(MEGAMORPHIC_GET, 1, name, isMethod, isScope);
         final MethodHandle guard   = getScriptObjectGuard(desc.getMethodType(), true);
         return new GuardedInvocation(invoker, guard);
@@ -2121,7 +2121,7 @@
 
         final GuardedInvocation inv = new SetMethodCreator(this, find, desc, explicitInstanceOfCheck).createGuardedInvocation();
 
-        final GuardedInvocation cinv = GlobalConstants.instance(Global.instance()).findSetMethod(find, this, inv, desc, request);
+        final GuardedInvocation cinv = Global.getConstants().findSetMethod(find, this, inv, desc, request);
         if (cinv != null) {
             return cinv;
         }
--- a/nashorn/src/jdk/nashorn/internal/runtime/ScriptRuntime.java	Wed Apr 23 16:13:47 2014 +0200
+++ b/nashorn/src/jdk/nashorn/internal/runtime/ScriptRuntime.java	Wed Apr 23 17:37:41 2014 +0200
@@ -451,7 +451,7 @@
      * @return JSON string representation of AST of the supplied code
      */
     public static String parse(final String code, final String name, final boolean includeLoc) {
-        return JSONWriter.parse(Context.getContextTrusted().getEnv(), code, name, includeLoc);
+        return JSONWriter.parse(Context.getContextTrusted(), code, name, includeLoc);
     }
 
     /**
--- a/nashorn/src/jdk/nashorn/internal/runtime/arrays/ContinuousArrayData.java	Wed Apr 23 16:13:47 2014 +0200
+++ b/nashorn/src/jdk/nashorn/internal/runtime/arrays/ContinuousArrayData.java	Wed Apr 23 17:37:41 2014 +0200
@@ -37,15 +37,11 @@
 import java.lang.invoke.SwitchPoint;
 
 import jdk.internal.dynalink.CallSiteDescriptor;
-import jdk.internal.dynalink.DynamicLinker;
 import jdk.internal.dynalink.linker.GuardedInvocation;
 import jdk.internal.dynalink.linker.LinkRequest;
 import jdk.nashorn.internal.lookup.Lookup;
-import jdk.nashorn.internal.objects.Global;
 import jdk.nashorn.internal.runtime.ScriptObject;
 import jdk.nashorn.internal.runtime.linker.NashornCallSiteDescriptor;
-import jdk.nashorn.internal.runtime.logging.DebugLogger;
-import jdk.nashorn.internal.runtime.logging.Loggable;
 import jdk.nashorn.internal.runtime.logging.Logger;
 
 /**
@@ -53,10 +49,7 @@
  * native arrays
  */
 @Logger(name="arrays")
-public abstract class ContinuousArrayData extends ArrayData implements Loggable {
-
-    /** Logger for array accessor linkage */
-    protected final DebugLogger log;
+public abstract class ContinuousArrayData extends ArrayData {
 
     private SwitchPoint sp;
 
@@ -66,17 +59,6 @@
      */
     protected ContinuousArrayData(final long length) {
         super(length);
-        this.log = initLogger(Global.instance());
-    }
-
-    @Override
-    public DebugLogger getLogger() {
-        return log;
-    }
-
-    @Override
-    public DebugLogger initLogger(final Global global) {
-        return global.getLogger(this.getClass());
     }
 
     private SwitchPoint ensureSwitchPointExists() {
@@ -249,10 +231,6 @@
             }
         }
 
-        if (log.isEnabled()) {
-            log.info(getClass().getSimpleName() + ": Missed fast GETTER " + clazz.getSimpleName() + " " + desc + " " + " line:" + DynamicLinker.getLinkedCallSiteLocation().getLineNumber());
-        }
-
         return null;
     }
 
@@ -290,10 +268,6 @@
             }
         }
 
-        if (log.isEnabled()) {
-            log.info(getClass().getSimpleName() + ": Missed fast SETTER " + clazz.getSimpleName() + " " + desc + " " + " line:" + DynamicLinker.getLinkedCallSiteLocation().getLineNumber());
-        }
-
         return null;
     }
 }
--- a/nashorn/src/jdk/nashorn/internal/runtime/arrays/TypedArrayData.java	Wed Apr 23 16:13:47 2014 +0200
+++ b/nashorn/src/jdk/nashorn/internal/runtime/arrays/TypedArrayData.java	Wed Apr 23 17:37:41 2014 +0200
@@ -31,7 +31,6 @@
 import java.nio.Buffer;
 
 import jdk.internal.dynalink.CallSiteDescriptor;
-import jdk.internal.dynalink.DynamicLinker;
 import jdk.internal.dynalink.linker.GuardedInvocation;
 import jdk.internal.dynalink.linker.LinkRequest;
 import jdk.nashorn.internal.lookup.Lookup;
@@ -101,22 +100,22 @@
     }
 
     @Override
-    public void shiftLeft(int by) {
+    public void shiftLeft(final int by) {
         throw new UnsupportedOperationException();
     }
 
     @Override
-    public ArrayData shiftRight(int by) {
+    public ArrayData shiftRight(final int by) {
         throw new UnsupportedOperationException();
     }
 
     @Override
-    public ArrayData ensure(long safeIndex) {
+    public ArrayData ensure(final long safeIndex) {
         return this;
     }
 
     @Override
-    public ArrayData shrink(long newLength) {
+    public ArrayData shrink(final long newLength) {
         throw new UnsupportedOperationException();
     }
 
@@ -126,17 +125,17 @@
     }
 
     @Override
-    public ArrayData delete(int index) {
+    public ArrayData delete(final int index) {
         return this;
     }
 
     @Override
-    public ArrayData delete(long fromIndex, long toIndex) {
+    public ArrayData delete(final long fromIndex, final long toIndex) {
         return this;
     }
 
     @Override
-    protected ArrayData convert(Class<?> type) {
+    protected ArrayData convert(final Class<?> type) {
         throw new UnsupportedOperationException();
     }
 
@@ -146,7 +145,7 @@
     }
 
     @Override
-    public ArrayData slice(long from, long to) {
+    public ArrayData slice(final long from, final long to) {
         throw new UnsupportedOperationException();
     }
 
@@ -190,10 +189,6 @@
             return inv;
         }
 
-        if (log.isEnabled()) {
-            log.info(clazz.getSimpleName() + ": Missed fast GETTER " + clazz.getSimpleName() + " " + desc + " " + " line:" + DynamicLinker.getLinkedCallSiteLocation().getLineNumber());
-        }
-
         return null;
     }
 
@@ -205,10 +200,6 @@
             return inv;
         }
 
-        if (log.isEnabled()) {
-            log.info(clazz.getSimpleName() + ": Missed fast SETTER " + clazz.getSimpleName() + " " + desc + " " + " line:" + DynamicLinker.getLinkedCallSiteLocation().getLineNumber());
-        }
-
         return null;
     }
 
--- a/nashorn/src/jdk/nashorn/internal/runtime/events/RecompilationEvent.java	Wed Apr 23 16:13:47 2014 +0200
+++ b/nashorn/src/jdk/nashorn/internal/runtime/events/RecompilationEvent.java	Wed Apr 23 17:37:41 2014 +0200
@@ -27,7 +27,7 @@
 
 import java.util.logging.Level;
 
-import jdk.nashorn.internal.objects.Global;
+import jdk.nashorn.internal.runtime.Context;
 import jdk.nashorn.internal.runtime.RecompilableScriptFunctionData;
 import jdk.nashorn.internal.runtime.RewriteException;
 
@@ -54,7 +54,7 @@
     @SuppressWarnings("javadoc")
     public RecompilationEvent(final Level level, final RewriteException rewriteException, final Object returnValue) {
         super(level, rewriteException);
-        assert Global.instance().getLogger(RecompilableScriptFunctionData.class).isEnabled() :
+        assert Context.getContext().getLogger(RecompilableScriptFunctionData.class).isEnabled() :
             "Unit test/instrumentation purpose only: RecompilationEvent instances should not be created without '--log=recompile', or we will leak memory in the general case";
         this.returnValue = returnValue;
     }
--- a/nashorn/src/jdk/nashorn/internal/runtime/logging/DebugLogger.java	Wed Apr 23 16:13:47 2014 +0200
+++ b/nashorn/src/jdk/nashorn/internal/runtime/logging/DebugLogger.java	Wed Apr 23 17:37:41 2014 +0200
@@ -179,6 +179,15 @@
     }
 
     /**
+     * Check if the logger is enabled
+     * @param logger logger to check, null will return false
+     * @return true if enabled
+     */
+    public static boolean isEnabled(final DebugLogger logger) {
+        return logger != null && logger.isEnabled();
+    }
+
+    /**
      * If you want to change the indent level of your logger, call indent with a new position.
      * Positions start at 0 and are increased by one for a new "tab"
      *
--- a/nashorn/src/jdk/nashorn/internal/runtime/logging/Loggable.java	Wed Apr 23 16:13:47 2014 +0200
+++ b/nashorn/src/jdk/nashorn/internal/runtime/logging/Loggable.java	Wed Apr 23 17:37:41 2014 +0200
@@ -24,7 +24,7 @@
  */
 package jdk.nashorn.internal.runtime.logging;
 
-import jdk.nashorn.internal.objects.Global;
+import jdk.nashorn.internal.runtime.Context;
 
 /**
  * Interface implemented by classes that are loggable.
@@ -40,13 +40,13 @@
  */
 public interface Loggable {
     /**
-     * Initialize a logger, by asking Global to get or create it
+     * Initialize a logger, by asking Context to get or create it
      * and then keep it in a table by name
      *
-     * @param global global
+     * @param context context
      * @return the initialized logger
      */
-    public DebugLogger initLogger(final Global global);
+    public DebugLogger initLogger(final Context context);
 
     /**
      * Return the logger in use
--- a/nashorn/src/jdk/nashorn/tools/Shell.java	Wed Apr 23 16:13:47 2014 +0200
+++ b/nashorn/src/jdk/nashorn/tools/Shell.java	Wed Apr 23 17:37:41 2014 +0200
@@ -245,7 +245,7 @@
 
             // For each file on the command line.
             for (final String fileName : files) {
-                final FunctionNode functionNode = new Parser(env, new Source(fileName, new File(fileName)), errors, env._strict).parse();
+                final FunctionNode functionNode = new Parser(env, new Source(fileName, new File(fileName)), errors, env._strict, FunctionNode.FIRST_FUNCTION_ID, 0, context.getLogger(Parser.class)).parse();
 
                 if (errors.getNumberOfErrors() != 0) {
                     return COMPILATION_ERROR;
--- a/nashorn/test/src/jdk/nashorn/internal/parser/ParserTest.java	Wed Apr 23 16:13:47 2014 +0200
+++ b/nashorn/test/src/jdk/nashorn/internal/parser/ParserTest.java	Wed Apr 23 17:37:41 2014 +0200
@@ -154,7 +154,7 @@
             };
             errors.setLimit(0);
             final Source source = new Source(file.getAbsolutePath(), buffer);
-            new Parser(context.getEnv(), source, errors, context.getEnv()._strict).parse();
+            new Parser(context.getEnv(), source, errors, context.getEnv()._strict, null).parse();
             if (errors.getNumberOfErrors() > 0) {
                 log("Parse failed: " + file.getAbsolutePath());
                 failed++;