8041434: Add synchronization to the common global constants structure

Reviewed-by: attila, hannesw
This commit is contained in:
Marcus Lagergren 2014-04-23 17:37:41 +02:00
parent 7bb2546460
commit e30eb1b6bb
35 changed files with 409 additions and 385 deletions

View file

@ -25,6 +25,7 @@ $FLAGS \
-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 \

View file

@ -48,6 +48,7 @@ import jdk.nashorn.internal.objects.Global;
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 @@ public final class ApplySpecialization implements Loggable {
* 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 @@ public final class ApplySpecialization implements Loggable {
}
@Override
public DebugLogger initLogger(final Global global) {
return global.getLogger(this.getClass());
public DebugLogger initLogger(final Context context) {
return context.getLogger(this.getClass());
}
/**

View file

@ -100,7 +100,6 @@ import jdk.nashorn.internal.ir.WhileNode;
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 @@ final class Attr extends NodeOperatorVisitor<OptimisticLexicalContext> implement
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 @@ final class Attr extends NodeOperatorVisitor<OptimisticLexicalContext> implement
}
@Override
public DebugLogger initLogger(final Global global) {
return global.getLogger(this.getClass());
public DebugLogger initLogger(final Context context) {
return context.getLogger(this.getClass());
}
@Override

View file

@ -70,7 +70,6 @@ import jdk.nashorn.internal.ir.debug.NashornTextifier;
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 @@ public class ClassEmitter implements Emitter {
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 @@ public class ClassEmitter implements Emitter {
* @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 @@ public class ClassEmitter implements Emitter {
* @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 @@ public class ClassEmitter implements Emitter {
* @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 @@ public class ClassEmitter implements Emitter {
defineCommonStatics(strictMode);
}
Context getContext() {
return context;
}
/**
* Returns the name of the compile unit class name.
* @return the name of the compile unit class name.
@ -393,13 +394,6 @@ public class ClassEmitter implements Emitter {
return str;
}
/**
* @return env used for class emission
*/
ScriptEnvironment getEnv() {
return env;
}
/**
* Call back from MethodEmitter for method start
*

View file

@ -240,7 +240,7 @@ final class CodeGenerator extends NodeOperatorVisitor<CodeGeneratorLexicalContex
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 @@ final class CodeGenerator extends NodeOperatorVisitor<CodeGeneratorLexicalContex
}
@Override
public DebugLogger initLogger(final Global global) {
return global.getLogger(this.getClass());
public DebugLogger initLogger(final Context context) {
return context.getLogger(this.getClass());
}
/**

View file

@ -34,6 +34,7 @@ import java.util.LinkedList;
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.IdentNode;
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 @@ public final class CompilationEnvironment {
private final CompilationPhases phases;
private final boolean optimistic;
private final Context context;
private final ParamTypeMap paramTypes;
private RecompilableScriptFunctionData compiledFunction;
@ -176,17 +180,21 @@ public final class CompilationEnvironment {
/**
* 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,6 +208,7 @@ public final class CompilationEnvironment {
* @param onDemand is this an on demand compilation
*/
public CompilationEnvironment(
final Context context,
final CompilationPhases phases,
final boolean strict,
final RecompilableScriptFunctionData compiledFunction,
@ -208,11 +217,13 @@ public final class CompilationEnvironment {
final Map<Integer, Type> invalidatedProgramPoints,
final int[] continuationEntryPoint,
final boolean onDemand) {
this(phases, paramTypeMap, invalidatedProgramPoints, compiledFunction, runtimeScope, continuationEntryPoint, strict, 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,6 +236,7 @@ public final class CompilationEnvironment {
* @param onDemand is this an on demand compilation
*/
public CompilationEnvironment(
final Context context,
final CompilationPhases phases,
final boolean strict,
final RecompilableScriptFunctionData compiledFunction,
@ -232,10 +244,11 @@ public final class CompilationEnvironment {
final ParamTypeMap paramTypeMap,
final Map<Integer, Type> invalidatedProgramPoints,
final boolean onDemand) {
this(phases, paramTypeMap, invalidatedProgramPoints, compiledFunction, runtimeScope, null, strict, 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 @@ public final class CompilationEnvironment {
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 @@ public final class CompilationEnvironment {
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])) {

View file

@ -53,7 +53,6 @@ import jdk.nashorn.internal.ir.TemporarySymbols;
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 @@ enum CompilationPhase {
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 @@ enum CompilationPhase {
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 @@ enum CompilationPhase {
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()) {
@ -238,7 +237,7 @@ enum CompilationPhase {
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 @@ enum CompilationPhase {
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));

View file

@ -61,8 +61,8 @@ import jdk.nashorn.internal.ir.FunctionNode.CompilationState;
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,9 +150,8 @@ public final class Compiler implements Loggable {
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()) {
@ -160,7 +159,6 @@ public final class Compiler implements Loggable {
}
}
}
}
/**
* Constructor - common entry point for generating code.
@ -177,7 +175,7 @@ public final class Compiler implements Loggable {
* @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 @@ public final class Compiler implements Loggable {
}
@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 @@ public final class Compiler implements Loggable {
}
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();

View file

@ -42,9 +42,9 @@ import jdk.nashorn.internal.ir.RuntimeNode.Request;
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 @@ final class FinalizeTypes extends NodeOperatorVisitor<LexicalContext> implements
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 @@ final class FinalizeTypes extends NodeOperatorVisitor<LexicalContext> implements
}
@Override
public DebugLogger initLogger(final Global global) {
return global.getLogger(this.getClass());
public DebugLogger initLogger(final Context context) {
return context.getLogger(this.getClass());
}
@Override

View file

@ -42,7 +42,7 @@ import jdk.nashorn.internal.ir.LexicalContext;
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 @@ final class FindScopeDepths extends NodeVisitor<LexicalContext> implements Logga
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 @@ final class FindScopeDepths extends NodeVisitor<LexicalContext> implements Logga
}
@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 class FindScopeDepths extends NodeVisitor<LexicalContext> implements Logga
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,

View file

@ -45,7 +45,7 @@ import jdk.nashorn.internal.ir.TernaryNode;
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 @@ final class FoldConstants extends NodeVisitor<LexicalContext> implements Loggabl
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 @@ final class FoldConstants extends NodeVisitor<LexicalContext> implements Loggabl
}
@Override
public DebugLogger initLogger(final Global global) {
return global.getLogger(this.getClass());
public DebugLogger initLogger(final Context context) {
return context.getLogger(this.getClass());
}
@Override

View file

@ -68,10 +68,10 @@ import jdk.nashorn.internal.ir.WhileNode;
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 @@ final class Lower extends NodeOperatorVisitor<BlockLexicalContext> implements Lo
/**
* Constructor.
*/
Lower(final CodeInstaller<?> installer) {
Lower(final Compiler compiler) {
super(new BlockLexicalContext() {
@Override
@ -142,8 +142,8 @@ final class Lower extends NodeOperatorVisitor<BlockLexicalContext> implements Lo
}
});
this.installer = installer;
this.log = initLogger(Global.instance());
this.installer = compiler.getCodeInstaller();
this.log = initLogger(compiler.getCompilationEnvironment().getContext());
}
@Override
@ -152,8 +152,8 @@ final class Lower extends NodeOperatorVisitor<BlockLexicalContext> implements Lo
}
@Override
public DebugLogger initLogger(final Global global) {
return global.getLogger(this.getClass());
public DebugLogger initLogger(final Context context) {
return context.getLogger(this.getClass());
}
@Override

View file

@ -97,10 +97,10 @@ import jdk.nashorn.internal.ir.RuntimeNode;
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 @@ public class MethodEmitter implements Emitter {
/** 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 @@ public class MethodEmitter implements Emitter {
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 @@ public class MethodEmitter implements Emitter {
* @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 @@ public class MethodEmitter implements Emitter {
* @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 @@ public class MethodEmitter implements Emitter {
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());

View file

@ -55,7 +55,6 @@ import java.util.LinkedList;
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,8 +146,7 @@ public final class ObjectClassGenerator implements Loggable {
public ObjectClassGenerator(final Context context) {
this.context = context;
assert context != null;
this.log = initLogger(Global.instance());
synchronized (ObjectClassGenerator.class) {
this.log = initLogger(context);
if (!initialized) {
initialized = true;
if (OBJECT_FIELDS_ONLY) {
@ -156,7 +154,6 @@ public final class ObjectClassGenerator implements Loggable {
}
}
}
}
@Override
public DebugLogger getLogger() {
@ -164,8 +161,8 @@ public final class ObjectClassGenerator implements Loggable {
}
@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 @@ public final class ObjectClassGenerator implements Loggable {
* @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;

View file

@ -47,8 +47,8 @@ import jdk.nashorn.internal.ir.UnaryNode;
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 @@ final class RangeAnalyzer extends NodeOperatorVisitor<LexicalContext> implements
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 @@ final class RangeAnalyzer extends NodeOperatorVisitor<LexicalContext> implements
}
@Override
public DebugLogger initLogger(final Global global) {
return global.getLogger(this.getClass());
public DebugLogger initLogger(final Context context) {
return context.getLogger(this.getClass());
}
@Override

View file

@ -70,7 +70,6 @@ import jdk.nashorn.internal.parser.Parser;
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 @@ public final class JSONWriter extends NodeVisitor<LexicalContext> {
/**
* 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 @@ public final class JSONWriter extends NodeVisitor<LexicalContext> {
}
@Override
public boolean enterBlockStatement(BlockStatement blockStatement) {
public boolean enterBlockStatement(final BlockStatement blockStatement) {
enterDefault(blockStatement);
type("BlockStatement");
@ -337,13 +336,13 @@ public final class JSONWriter extends NodeVisitor<LexicalContext> {
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 @@ public final class JSONWriter extends NodeVisitor<LexicalContext> {
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 @@ public final class JSONWriter extends NodeVisitor<LexicalContext> {
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('"');
}
}
}

View file

@ -37,8 +37,8 @@ import java.util.Arrays;
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 @@ public final class MethodHandleFactory {
* 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 @@ public final class MethodHandleFactory {
}
@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

View file

@ -44,15 +44,13 @@ import java.util.HashMap;
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.ScriptingFunctions;
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 @@ public final class Global extends ScriptObject implements Scope {
// 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 @@ public final class Global extends ScriptObject implements Scope {
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)));
}
}
/**
@ -494,6 +487,15 @@ public final class Global extends ScriptObject implements Scope {
return global;
}
/**
* 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 @@ public final class Global extends ScriptObject implements Scope {
// synonym for "arguments" in scripting mode
addOwnProperty("$ARG", argumentsFlags, argumentsObject);
}
initLoggers();
}
private void initErrorObjects() {
@ -2097,7 +2097,7 @@ public final class Global extends ScriptObject implements Scope {
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 @@ public final class Global extends ScriptObject implements Scope {
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;
}
}

View file

@ -289,7 +289,7 @@ public final class NativeFunction {
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 @@ public final class NativeFunction {
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) {

View file

@ -105,7 +105,7 @@ import jdk.nashorn.internal.ir.UnaryNode;
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 @@ import jdk.nashorn.internal.runtime.logging.Logger;
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 @@ public class Parser extends AbstractParser implements Loggable {
* @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 @@ public class Parser extends AbstractParser implements Loggable {
* @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,8 +179,9 @@ public class Parser extends AbstractParser implements Loggable {
* @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.namespace = new Namespace(env.getNamespace());
@ -199,7 +201,7 @@ public class Parser extends AbstractParser implements Loggable {
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 @@ public class Parser extends AbstractParser implements Loggable {
}
@Override
public DebugLogger initLogger(final Global global) {
return global.getLogger(this.getClass());
public DebugLogger initLogger(final Context context) {
return context.getLogger(this.getClass());
}
/**

View file

@ -691,8 +691,14 @@ public class AccessorProperty extends Property {
private MethodHandle debug(final MethodHandle mh, final Class<?> forType, final Class<?> type, final String tag) {
if (Global.hasInstance()) {
return Global.instance().addLoggingToHandle(
if (!Global.hasInstance()) {
return mh;
}
final Context context = Context.getContextTrusted();
assert context != null;
return context.addLoggingToHandle(
ObjectClassGenerator.class,
Level.INFO,
mh,
@ -706,13 +712,15 @@ public class AccessorProperty extends Property {
});
}
return mh;
private MethodHandle debugReplace(final Class<?> oldType, final Class<?> newType, final PropertyMap oldMap, final PropertyMap newMap) {
if (!Global.hasInstance()) {
return REPLACE_MAP;
}
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(
final Context context = Context.getContextTrusted();
assert context != null;
MethodHandle mh = context.addLoggingToHandle(
ObjectClassGenerator.class,
REPLACE_MAP,
new Supplier<String>() {
@ -722,7 +730,7 @@ public class AccessorProperty extends Property {
}
});
mh = global.addLoggingToHandle(
mh = context.addLoggingToHandle(
ObjectClassGenerator.class,
Level.FINEST,
mh,
@ -737,12 +745,15 @@ public class AccessorProperty extends Property {
return mh;
}
return REPLACE_MAP;
private static MethodHandle debugInvalidate(final String key, final SwitchPoint sp) {
if (!Global.hasInstance()) {
return INVALIDATE_SP;
}
private static MethodHandle debugInvalidate(final String key, final SwitchPoint sp) {
if (Global.hasInstance()) {
return Global.instance().addLoggingToHandle(
final Context context = Context.getContextTrusted();
assert context != null;
return context.addLoggingToHandle(
ObjectClassGenerator.class,
INVALIDATE_SP,
new Supplier<String>() {
@ -753,9 +764,6 @@ public class AccessorProperty extends Property {
});
}
return INVALIDATE_SP;
}
private static MethodHandle findOwnMH_S(final String name, final Class<?> rtype, final Class<?>... types) {
return MH.findStatic(LOOKUP, AccessorProperty.class, name, MH.type(rtype, types));
}

View file

@ -41,7 +41,6 @@ import java.util.logging.Level;
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 @@ final class CompiledFunction {
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 @@ final class CompiledFunction {
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();
}

View file

@ -33,6 +33,7 @@ import static jdk.nashorn.internal.runtime.ScriptRuntime.UNDEFINED;
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.CodeSource;
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.codegen.ObjectClassGenerator;
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 @@ public final class Context {
// 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 @@ public final class Context {
if (env._fullversion) {
getErr().println("nashorn full version " + Version.fullVersion());
}
initLoggers();
}
/**
@ -916,14 +927,14 @@ public final class Context {
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 @@ public final class Context {
final CompilationPhases phases = CompilationEnvironment.CompilationPhases.EAGER;
final Compiler compiler = new Compiler(
new CompilationEnvironment(
this,
phases.
makeOptimistic(
ScriptEnvironment.globalOptimistic()),
@ -1032,4 +1044,79 @@ public final class Context {
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;
}
}

View file

@ -44,7 +44,6 @@ import jdk.internal.dynalink.linker.GuardedInvocation;
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 @@ import jdk.nashorn.internal.runtime.logging.Logger;
* 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 @@ public final class GlobalConstants implements Loggable {
*/
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 @@ public final class GlobalConstants implements Loggable {
}
@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 @@ public final class GlobalConstants implements Loggable {
* 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 @@ public final class GlobalConstants implements Loggable {
* @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 @@ public final class GlobalConstants implements Loggable {
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 @@ public final class GlobalConstants implements Loggable {
*
* @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 @@ public final class GlobalConstants implements Loggable {
* @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 @@ public final class GlobalConstants implements Loggable {
*
* @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;
}

View file

@ -50,7 +50,6 @@ import jdk.nashorn.internal.codegen.types.Type;
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 @@ public final class RecompilableScriptFunctionData extends ScriptFunctionData imp
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 @@ public final class RecompilableScriptFunctionData extends ScriptFunctionData imp
* @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 @@ public final class RecompilableScriptFunctionData extends ScriptFunctionData imp
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 @@ public final class RecompilableScriptFunctionData extends ScriptFunctionData imp
nfn.setParent(this);
}
this.log = initLogger(Global.instance());
this.log = initLogger(context);
}
@Override
@ -181,8 +185,8 @@ public final class RecompilableScriptFunctionData extends ScriptFunctionData imp
}
@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 @@ public final class RecompilableScriptFunctionData extends ScriptFunctionData imp
// 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 @@ public final class RecompilableScriptFunctionData extends ScriptFunctionData imp
final Compiler compiler = new Compiler(
new CompilationEnvironment(
context,
CompilationPhases.EAGER.makeOptimistic(),
isStrict(),
this,
@ -454,6 +460,7 @@ public final class RecompilableScriptFunctionData extends ScriptFunctionData imp
final CompilationPhases phases = CompilationPhases.EAGER;
final Compiler compiler = new Compiler(
new CompilationEnvironment(
context,
phases.makeOptimistic(ScriptEnvironment.globalOptimistic()),
isStrict(),
this,
@ -744,7 +751,7 @@ public final class RecompilableScriptFunctionData extends ScriptFunctionData imp
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;

View file

@ -681,7 +681,7 @@ public abstract class ScriptFunction extends ScriptObject {
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);

View file

@ -918,7 +918,7 @@ public abstract class ScriptObject implements PropertyAccess {
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 @@ public abstract class ScriptObject implements PropertyAccess {
}
}
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 @@ public abstract class ScriptObject implements PropertyAccess {
}
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 @@ public abstract class ScriptObject implements PropertyAccess {
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;
}

View file

@ -451,7 +451,7 @@ public final class ScriptRuntime {
* @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);
}
/**

View file

@ -37,15 +37,11 @@ import java.lang.invoke.MethodType;
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 @@ import jdk.nashorn.internal.runtime.logging.Logger;
* 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 @@ public abstract class ContinuousArrayData extends ArrayData implements Loggable
*/
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 @@ public abstract class ContinuousArrayData extends ArrayData implements Loggable
}
}
if (log.isEnabled()) {
log.info(getClass().getSimpleName() + ": Missed fast GETTER " + clazz.getSimpleName() + " " + desc + " " + " line:" + DynamicLinker.getLinkedCallSiteLocation().getLineNumber());
}
return null;
}
@ -290,10 +268,6 @@ public abstract class ContinuousArrayData extends ArrayData implements Loggable
}
}
if (log.isEnabled()) {
log.info(getClass().getSimpleName() + ": Missed fast SETTER " + clazz.getSimpleName() + " " + desc + " " + " line:" + DynamicLinker.getLinkedCallSiteLocation().getLineNumber());
}
return null;
}
}

View file

@ -31,7 +31,6 @@ import java.lang.invoke.MethodHandle;
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 @@ public abstract class TypedArrayData<T extends Buffer> extends ContinuousArrayDa
}
@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 @@ public abstract class TypedArrayData<T extends Buffer> extends ContinuousArrayDa
}
@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 @@ public abstract class TypedArrayData<T extends Buffer> extends ContinuousArrayDa
}
@Override
public ArrayData slice(long from, long to) {
public ArrayData slice(final long from, final long to) {
throw new UnsupportedOperationException();
}
@ -190,10 +189,6 @@ public abstract class TypedArrayData<T extends Buffer> extends ContinuousArrayDa
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 @@ public abstract class TypedArrayData<T extends Buffer> extends ContinuousArrayDa
return inv;
}
if (log.isEnabled()) {
log.info(clazz.getSimpleName() + ": Missed fast SETTER " + clazz.getSimpleName() + " " + desc + " " + " line:" + DynamicLinker.getLinkedCallSiteLocation().getLineNumber());
}
return null;
}

View file

@ -27,7 +27,7 @@ package jdk.nashorn.internal.runtime.events;
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 @@ public final class RecompilationEvent extends RuntimeEvent<RewriteException> {
@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;
}

View file

@ -178,6 +178,15 @@ public final class DebugLogger {
return isEnabled;
}
/**
* 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"

View file

@ -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 @@ import jdk.nashorn.internal.objects.Global;
*/
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

View file

@ -245,7 +245,7 @@ public class Shell {
// 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;

View file

@ -154,7 +154,7 @@ public class ParserTest {
};
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++;