8038426: Move all loggers from process wide scope into Global scope

Reviewed-by: attila, hannesw
This commit is contained in:
Marcus Lagergren 2014-04-23 16:13:47 +02:00
parent 6163a42a8e
commit 7bb2546460
42 changed files with 1136 additions and 876 deletions

View File

@ -45,7 +45,9 @@ import jdk.nashorn.internal.ir.LexicalContext;
import jdk.nashorn.internal.ir.Node;
import jdk.nashorn.internal.ir.visitor.NodeVisitor;
import jdk.nashorn.internal.objects.Global;
import jdk.nashorn.internal.runtime.DebugLogger;
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.RecompilableScriptFunctionData;
import jdk.nashorn.internal.runtime.options.Options;
@ -80,7 +82,8 @@ import jdk.nashorn.internal.runtime.options.Options;
* </pre>
*/
public final class ApplySpecialization {
@Logger(name="apply2call")
public final class ApplySpecialization implements Loggable {
private static final boolean USE_APPLY2CALL = Options.getBooleanProperty("nashorn.apply2call", true);
@ -90,7 +93,7 @@ public final class ApplySpecialization {
private final MethodType actualCallSiteType;
private static final DebugLogger LOG = new DebugLogger("apply2call");
private final DebugLogger log;
private static final String ARGUMENTS = ARGUMENTS_VAR.symbolName();
@ -98,14 +101,6 @@ public final class ApplySpecialization {
private boolean finished;
/**
* Return the apply to call specialization logger g
* @return the logger
*/
public static DebugLogger getLogger() {
return LOG;
}
/**
* Apply specialization optimization. Try to explode arguments and call
* applies as calls if they just pass on the "arguments" array and
@ -116,9 +111,20 @@ public final class ApplySpecialization {
* @param actualCallSiteType actual call site type that we use (not Object[] varargs)
*/
public ApplySpecialization(final RecompilableScriptFunctionData data, final FunctionNode functionNode, final MethodType actualCallSiteType) {
this.data = data;
this.functionNode = functionNode;
this.data = data;
this.functionNode = functionNode;
this.actualCallSiteType = actualCallSiteType;
this.log = initLogger(Global.instance());
}
@Override
public DebugLogger getLogger() {
return log;
}
@Override
public DebugLogger initLogger(final Global global) {
return global.getLogger(this.getClass());
}
/**
@ -176,7 +182,7 @@ public final class ApplySpecialization {
}
});
} catch (final UnsupportedOperationException e) {
LOG.fine("'arguments' escapes, is not used in standard call dispatch, or is reassigned in '" + functionNode.getName() + "'. Aborting");
log.fine("'arguments' escapes, is not used in standard call dispatch, or is reassigned in '" + functionNode.getName() + "'. Aborting");
return true; //bad
}
@ -204,7 +210,7 @@ public final class ApplySpecialization {
changed = false;
if (!Global.instance().isSpecialNameValid("apply")) {
LOG.fine("Apply transform disabled: apply/call overridden");
log.fine("Apply transform disabled: apply/call overridden");
assert !Global.instance().isSpecialNameValid("call") : "call and apply should have the same SwitchPoint";
return finish();
}
@ -251,7 +257,7 @@ public final class ApplySpecialization {
changed = true;
final CallNode newCallNode = callNode.setArgs(newArgs).setIsApplyToCall();
LOG.fine("Transformed " + callNode + " from apply to call => " + newCallNode + " in '" + functionNode.getName() + "'");
log.fine("Transformed " + callNode + " from apply to call => " + newCallNode + " in '" + functionNode.getName() + "'");
return newCallNode;
}
@ -265,7 +271,7 @@ public final class ApplySpecialization {
setParameters(null, newParams);
}
LOG.info("Successfully specialized apply to call in '" + functionNode.getName() + "' id=" + functionNode.getId() + " signature=" + actualCallSiteType);
log.info("Successfully specialized apply to call in '" + functionNode.getName() + "' id=" + functionNode.getId() + " signature=" + actualCallSiteType);
return finish();
}

View File

@ -59,6 +59,7 @@ import java.util.Iterator;
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.BinaryNode;
@ -99,13 +100,16 @@ 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;
import jdk.nashorn.internal.runtime.DebugLogger;
import jdk.nashorn.internal.runtime.JSType;
import jdk.nashorn.internal.runtime.Property;
import jdk.nashorn.internal.runtime.PropertyMap;
import jdk.nashorn.internal.runtime.logging.DebugLogger;
import jdk.nashorn.internal.runtime.logging.Loggable;
import jdk.nashorn.internal.runtime.logging.Logger;
/**
* This is the attribution pass of the code generator. Attr takes Lowered IR,
@ -121,8 +125,8 @@ import jdk.nashorn.internal.runtime.PropertyMap;
* but in general, this is where the main symbol type information is
* computed.
*/
final class Attr extends NodeOperatorVisitor<OptimisticLexicalContext> {
@Logger(name="Attr")
final class Attr extends NodeOperatorVisitor<OptimisticLexicalContext> implements Loggable {
private final CompilationEnvironment env;
@ -146,8 +150,8 @@ final class Attr extends NodeOperatorVisitor<OptimisticLexicalContext> {
private int catchNestingLevel;
private static final DebugLogger LOG = new DebugLogger("attr");
private static final boolean DEBUG = LOG.isEnabled();
private final DebugLogger log;
private final boolean debug;
private final TemporarySymbols temporarySymbols;
@ -160,6 +164,18 @@ final class Attr extends NodeOperatorVisitor<OptimisticLexicalContext> {
this.temporarySymbols = temporarySymbols;
this.localDefs = new ArrayDeque<>();
this.localUses = new ArrayDeque<>();
this.log = initLogger(Global.instance());
this.debug = log.isEnabled();
}
@Override
public DebugLogger getLogger() {
return log;
}
@Override
public DebugLogger initLogger(final Global global) {
return global.getLogger(this.getClass());
}
@Override
@ -564,7 +580,7 @@ final class Attr extends NodeOperatorVisitor<OptimisticLexicalContext> {
if (newFunctionNode.usesSelfSymbol()) {
syntheticInitializers = new ArrayList<>(2);
LOG.info("Accepting self symbol init for ", newFunctionNode.getName());
log.info("Accepting self symbol init for ", newFunctionNode.getName());
// "var fn = :callee"
syntheticInitializers.add(createSyntheticInitializer(newFunctionNode.getIdent(), CALLEE, newFunctionNode));
}
@ -628,8 +644,8 @@ final class Attr extends NodeOperatorVisitor<OptimisticLexicalContext> {
if (identNode.isPropertyName()) {
// assign a pseudo symbol to property name
final Symbol pseudoSymbol = pseudoSymbol(name);
LOG.info("IdentNode is property name -> assigning pseudo symbol ", pseudoSymbol);
LOG.unindent();
log.info("IdentNode is property name -> assigning pseudo symbol ", pseudoSymbol);
log.unindent();
return end(identNode.setSymbol(lc, pseudoSymbol));
}
@ -639,7 +655,7 @@ final class Attr extends NodeOperatorVisitor<OptimisticLexicalContext> {
//If an existing symbol with the name is found, use that otherwise, declare a new one
if (symbol != null) {
LOG.info("Existing symbol = ", symbol);
log.info("Existing symbol = ", symbol);
if (symbol.isFunctionSelf()) {
final FunctionNode functionNode = lc.getDefiningFunction(symbol);
assert functionNode != null;
@ -667,7 +683,7 @@ final class Attr extends NodeOperatorVisitor<OptimisticLexicalContext> {
// if symbol is non-local or we're in a with block, we need to put symbol in scope (if it isn't already)
maybeForceScope(symbol);
} else {
LOG.info("No symbol exists. Declare undefined: ", symbol);
log.info("No symbol exists. Declare undefined: ", symbol);
symbol = defineGlobalSymbol(block, name);
// we have never seen this before, it can be undefined
newType(symbol, Type.OBJECT); // TODO unknown -we have explicit casts anyway?
@ -1686,7 +1702,7 @@ final class Attr extends NodeOperatorVisitor<OptimisticLexicalContext> {
final Type callSiteParamType = env.getParamType(functionNode, pos);
if (callSiteParamType != null) {
LOG.info("Callsite type override for parameter " + pos + " " + paramSymbol + " => " + callSiteParamType);
log.info("Callsite type override for parameter " + pos + " " + paramSymbol + " => " + callSiteParamType);
newType(paramSymbol, callSiteParamType);
} else {
// When we're using optimistic compilation, we'll generate specialized versions of the functions anyway
@ -1699,7 +1715,7 @@ final class Attr extends NodeOperatorVisitor<OptimisticLexicalContext> {
// with Type.UNKNOWN.
newType(paramSymbol, isOptimistic ? Type.OBJECT : Type.UNKNOWN);
}
LOG.info("Initialized param ", pos, "=", paramSymbol);
log.info("Initialized param ", pos, "=", paramSymbol);
pos++;
}
@ -1771,7 +1787,7 @@ final class Attr extends NodeOperatorVisitor<OptimisticLexicalContext> {
final String key = property.getKey();
final Symbol symbol = defineGlobalSymbol(block, key);
newType(symbol, Type.OBJECT);
LOG.info("Added global symbol from property map ", symbol);
log.info("Added global symbol from property map ", symbol);
}
}
@ -1811,8 +1827,8 @@ final class Attr extends NodeOperatorVisitor<OptimisticLexicalContext> {
}
final Type from = node.getType();
if (!Type.areEquivalent(from, to) && Type.widest(from, to) == to) {
if (LOG.isEnabled()) {
LOG.fine("Had to post pass widen '", node, "' ", Debug.id(node), " from ", node.getType(), " to ", to);
if (log.isEnabled()) {
log.fine("Had to post pass widen '", node, "' ", Debug.id(node), " from ", node.getType(), " to ", to);
}
Symbol symbol = node.getSymbol();
if (symbol.isShared() && symbol.wouldChangeType(to)) {
@ -1983,7 +1999,7 @@ final class Attr extends NodeOperatorVisitor<OptimisticLexicalContext> {
}
private Expression ensureSymbol(final Expression expr, final Type type) {
LOG.info("New TEMPORARY added to ", lc.getCurrentFunction().getName(), " type=", type);
log.info("New TEMPORARY added to ", lc.getCurrentFunction().getName(), " type=", type);
return temporarySymbols.ensureSymbol(lc, type, expr);
}
@ -2030,14 +2046,14 @@ final class Attr extends NodeOperatorVisitor<OptimisticLexicalContext> {
*/
private void tagNeverOptimistic(final Expression expr) {
if (expr instanceof Optimistic) {
LOG.info("Tagging TypeOverride node '" + expr + "' never optimistic");
log.info("Tagging TypeOverride node '" + expr + "' never optimistic");
neverOptimistic.add(tag((Optimistic)expr));
}
}
private void tagOptimistic(final Expression expr) {
if (expr instanceof Optimistic) {
LOG.info("Tagging TypeOverride node '" + expr + "' as optimistic");
log.info("Tagging TypeOverride node '" + expr + "' as optimistic");
optimistic.add(tag((Optimistic)expr));
}
}
@ -2106,7 +2122,7 @@ final class Attr extends NodeOperatorVisitor<OptimisticLexicalContext> {
expr = (T)expr.setSymbol(lc, symbol.createUnshared(symbol.getName()));
}
}
LOG.fine(expr, " turned optimistic with type=", optimisticType);
log.fine(expr, " turned optimistic with type=", optimisticType);
assert ((Optimistic)expr).isOptimistic();
}
}
@ -2118,17 +2134,17 @@ final class Attr extends NodeOperatorVisitor<OptimisticLexicalContext> {
return defineSymbol(lc.getCurrentBlock(), name, IS_VAR | IS_INTERNAL).setType(type); //NASHORN-73
}
private static void newType(final Symbol symbol, final Type type) {
private void newType(final Symbol symbol, final Type type) {
final Type oldType = symbol.getSymbolType();
symbol.setType(type);
if (symbol.getSymbolType() != oldType) {
LOG.info("New TYPE ", type, " for ", symbol," (was ", oldType, ")");
log.info("New TYPE ", type, " for ", symbol," (was ", oldType, ")");
}
if (symbol.isParam()) {
symbol.setType(type);
LOG.info("Param type change ", symbol);
log.info("Param type change ", symbol);
}
}
@ -2156,12 +2172,12 @@ final class Attr extends NodeOperatorVisitor<OptimisticLexicalContext> {
}
private void addLocalDef(final String name) {
LOG.info("Adding local def of symbol: '", name, "'");
log.info("Adding local def of symbol: '", name, "'");
localDefs.peek().add(name);
}
private void removeLocalDef(final String name) {
LOG.info("Removing local def of symbol: '", name, "'");
log.info("Removing local def of symbol: '", name, "'");
localDefs.peek().remove(name);
}
@ -2170,7 +2186,7 @@ final class Attr extends NodeOperatorVisitor<OptimisticLexicalContext> {
}
private void addLocalUse(final String name) {
LOG.info("Adding local use of symbol: '", name, "'");
log.info("Adding local use of symbol: '", name, "'");
localUses.peek().add(name);
}
@ -2183,7 +2199,7 @@ final class Attr extends NodeOperatorVisitor<OptimisticLexicalContext> {
return;
}
if (symbolType != type) {
LOG.info("Infer parameter type " + symbol + " ==> " + type + " " + lc.getCurrentFunction().getSource().getName() + " " + lc.getCurrentFunction().getName());
log.info("Infer parameter type " + symbol + " ==> " + type + " " + lc.getCurrentFunction().getSource().getName() + " " + lc.getCurrentFunction().getName());
}
symbol.setType(type); //will be overwritten by object later if pessimistic anyway
lc.logOptimisticAssumption(symbol, type);
@ -2230,7 +2246,7 @@ final class Attr extends NodeOperatorVisitor<OptimisticLexicalContext> {
}
private boolean start(final Node node, final boolean printNode) {
if (DEBUG) {
if (debug) {
final StringBuilder sb = new StringBuilder();
sb.append("[ENTER ").
@ -2240,8 +2256,8 @@ final class Attr extends NodeOperatorVisitor<OptimisticLexicalContext> {
append(" in '").
append(lc.getCurrentFunction().getName()).
append("'");
LOG.info(sb);
LOG.indent();
log.info(sb);
log.indent();
}
return true;
@ -2256,7 +2272,7 @@ final class Attr extends NodeOperatorVisitor<OptimisticLexicalContext> {
// If we're done with a statement, all temporaries can be reused.
temporarySymbols.reuse();
}
if (DEBUG) {
if (debug) {
final StringBuilder sb = new StringBuilder();
sb.append("[LEAVE ").
@ -2276,8 +2292,8 @@ final class Attr extends NodeOperatorVisitor<OptimisticLexicalContext> {
}
}
LOG.unindent();
LOG.info(sb);
log.unindent();
log.info(sb);
}
return node;

View File

@ -133,7 +133,6 @@ import jdk.nashorn.internal.parser.Lexer.RegexToken;
import jdk.nashorn.internal.parser.TokenType;
import jdk.nashorn.internal.runtime.Context;
import jdk.nashorn.internal.runtime.Debug;
import jdk.nashorn.internal.runtime.DebugLogger;
import jdk.nashorn.internal.runtime.ECMAException;
import jdk.nashorn.internal.runtime.JSType;
import jdk.nashorn.internal.runtime.OptimisticReturnFilters;
@ -149,6 +148,9 @@ import jdk.nashorn.internal.runtime.Undefined;
import jdk.nashorn.internal.runtime.UnwarrantedOptimismException;
import jdk.nashorn.internal.runtime.arrays.ArrayData;
import jdk.nashorn.internal.runtime.linker.LinkerCallSite;
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;
/**
@ -170,7 +172,8 @@ import jdk.nashorn.internal.runtime.options.Options;
* The CodeGenerator visits nodes only once, tags them as resolved and emits
* bytecode for them.
*/
final class CodeGenerator extends NodeOperatorVisitor<CodeGeneratorLexicalContext> {
@Logger(name="codegen")
final class CodeGenerator extends NodeOperatorVisitor<CodeGeneratorLexicalContext> implements Loggable {
private static final Type SCOPE_TYPE = Type.typeFor(ScriptObject.class);
@ -214,7 +217,7 @@ final class CodeGenerator extends NodeOperatorVisitor<CodeGeneratorLexicalContex
/** Current compile unit */
private CompileUnit unit;
private static final DebugLogger LOG = new DebugLogger("codegen", "nashorn.codegen.debug");
private final DebugLogger log;
/** From what size should we use spill instead of fields for JavaScript objects? */
private static final int OBJECT_SPILL_THRESHOLD = Options.getIntProperty("nashorn.spill.threshold", 256);
@ -237,6 +240,17 @@ final class CodeGenerator extends NodeOperatorVisitor<CodeGeneratorLexicalContex
super(new CodeGeneratorLexicalContext());
this.compiler = compiler;
this.callSiteFlags = compiler.getEnv()._callsite_flags;
this.log = initLogger(Global.instance());
}
@Override
public DebugLogger getLogger() {
return log;
}
@Override
public DebugLogger initLogger(final Global global) {
return global.getLogger(this.getClass());
}
/**
@ -1511,7 +1525,7 @@ final class CodeGenerator extends NodeOperatorVisitor<CodeGeneratorLexicalContex
// exact type closure and deduplicate based on that, or just decide that functions in finally blocks aren't
// worth it, and generate one method with most generic type closure.
if (!emittedMethods.contains(fnName)) {
LOG.info("=== BEGIN ", fnName);
log.info("=== BEGIN ", fnName);
assert functionNode.getCompileUnit() != null : "no compile unit for " + fnName + " " + Debug.id(functionNode);
unit = lc.pushCompileUnit(functionNode.getCompileUnit());
@ -1550,7 +1564,7 @@ final class CodeGenerator extends NodeOperatorVisitor<CodeGeneratorLexicalContex
method.end(); // wrap up this method
unit = lc.popCompileUnit(functionNode.getCompileUnit());
method = lc.popMethodEmitter(method);
LOG.info("=== END ", functionNode.getName());
log.info("=== END ", functionNode.getName());
} else {
markOptimistic = false;
}

View File

@ -1,6 +1,30 @@
/*
* Copyright (c) 2010, 2014, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package jdk.nashorn.internal.codegen;
import static jdk.nashorn.internal.codegen.Compiler.info;
import static jdk.nashorn.internal.ir.FunctionNode.CompilationState.ATTR;
import static jdk.nashorn.internal.ir.FunctionNode.CompilationState.CONSTANT_FOLDED;
import static jdk.nashorn.internal.ir.FunctionNode.CompilationState.FINALIZED;
@ -29,6 +53,7 @@ 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;
@ -128,7 +153,7 @@ enum CompilationPhase {
accept(new Attr(compiler.getCompilationEnvironment(), ts));
if (compiler.getEnv()._print_mem_usage) {
info("Attr temporary symbol count:", ts.getTotalSymbolCount());
compiler.getLogger().info("Attr temporary symbol count:", ts.getTotalSymbolCount());
}
return newFunctionNode;
@ -213,7 +238,7 @@ enum CompilationPhase {
final Type rangeType = range.getType();
if (!rangeType.isUnknown() && !Type.areEquivalent(symbolType, rangeType) && Type.widest(symbolType, rangeType) == symbolType) { //we can narrow range
RangeAnalyzer.LOG.info("[", lc.getCurrentFunction().getName(), "] ", symbol, " can be ", range.getType(), " ", symbol.getRange());
Global.instance().getLogger(RangeAnalyzer.class).info("[", lc.getCurrentFunction().getName(), "] ", symbol, " can be ", range.getType(), " ", symbol.getRange());
return expr.setSymbol(lc, symbol.setTypeOverrideShared(range.getType(), compiler.getTemporarySymbols()));
}
}
@ -332,7 +357,7 @@ enum CompilationPhase {
compiler.getCodeInstaller().verify(bytecode);
}
DumpBytecode.dumpBytecode(env, bytecode, className);
DumpBytecode.dumpBytecode(env, compiler, bytecode, className);
}
return newFunctionNode;

View File

@ -51,6 +51,7 @@ import java.util.Map.Entry;
import java.util.Set;
import java.util.TreeSet;
import java.util.logging.Level;
import jdk.internal.dynalink.support.NameCodec;
import jdk.nashorn.internal.codegen.ClassEmitter.Flag;
import jdk.nashorn.internal.codegen.CompilationEnvironment.CompilationPhases;
@ -60,12 +61,15 @@ 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.DebugLogger;
import jdk.nashorn.internal.runtime.RecompilableScriptFunctionData;
import jdk.nashorn.internal.runtime.ScriptEnvironment;
import jdk.nashorn.internal.runtime.Source;
import jdk.nashorn.internal.runtime.Timing;
import jdk.nashorn.internal.runtime.logging.DebugLogger;
import jdk.nashorn.internal.runtime.logging.Loggable;
import jdk.nashorn.internal.runtime.logging.Logger;
/**
* Responsible for converting JavaScripts to java byte code. Main entry
@ -73,7 +77,8 @@ import jdk.nashorn.internal.runtime.Timing;
* predefined Code installation policy, given to it at construction time.
* @see CodeInstaller
*/
public final class Compiler {
@Logger(name="compiler")
public final class Compiler implements Loggable {
/** Name of the scripts package */
public static final String SCRIPTS_PACKAGE = "jdk/nashorn/internal/scripts";
@ -104,21 +109,9 @@ public final class Compiler {
/** logger for compiler, trampolines, splits and related code generation events
* that affect classes */
private static final DebugLogger LOG = new DebugLogger("compiler");
private final DebugLogger log;
/**
* Get the logger used for this compiler
* @return logger
*/
public static DebugLogger getLogger() {
return LOG;
}
static {
if (!ScriptEnvironment.globalOptimistic()) {
LOG.warning("Running without optimistic types. This is a configuration that may be deprecated.");
}
}
private static boolean initialized = false;
/**
* This array contains names that need to be reserved at the start
@ -157,6 +150,16 @@ public final class Compiler {
this.constantData = new ConstantData();
this.compileUnits = new TreeSet<>();
this.bytecode = new LinkedHashMap<>();
this.log = initLogger(Global.instance());
synchronized (Compiler.class) {
if (!initialized) {
initialized = true;
if (!ScriptEnvironment.globalOptimistic()) {
log.warning("Running without optimistic types. This is a configuration that may be deprecated.");
}
}
}
}
/**
@ -177,12 +180,22 @@ public final class Compiler {
this(new CompilationEnvironment(CompilationPhases.EAGER, scriptEnv._strict), scriptEnv, null);
}
private static void printMemoryUsage(final String phaseName, final FunctionNode functionNode) {
if (!LOG.isEnabled()) {
@Override
public DebugLogger getLogger() {
return log;
}
@Override
public DebugLogger initLogger(final Global global) {
return global.getLogger(this.getClass());
}
private void printMemoryUsage(final String phaseName, final FunctionNode functionNode) {
if (!log.isEnabled()) {
return;
}
info(phaseName, "finished. Doing IR size calculation...");
log.info(phaseName, "finished. Doing IR size calculation...");
final ObjectSizeCalculator osc = new ObjectSizeCalculator(ObjectSizeCalculator.getEffectiveMemoryLayoutSpecification());
osc.calculateObjectSize(functionNode);
@ -195,7 +208,7 @@ public final class Compiler {
append(" Total size = ").
append(totalSize / 1024 / 1024).
append("MB");
LOG.info(sb);
log.info(sb);
Collections.sort(list, new Comparator<ClassHistogramElement>() {
@Override
@ -212,9 +225,9 @@ public final class Compiler {
});
for (final ClassHistogramElement e : list) {
final String line = String.format(" %-48s %10d bytes (%8d instances)", e.getClazz(), e.getBytes(), e.getInstances());
info(line);
log.info(line);
if (e.getBytes() < totalSize / 200) {
info(" ...");
log.info(" ...");
break; // never mind, so little memory anyway
}
}
@ -258,8 +271,8 @@ public final class Compiler {
newFunctionNode.uniqueName(reservedName);
}
final boolean fine = LOG.levelFinerThanOrEqual(Level.FINE);
final boolean info = LOG.levelFinerThanOrEqual(Level.INFO);
final boolean fine = log.levelFinerThanOrEqual(Level.FINE);
final boolean info = log.levelFinerThanOrEqual(Level.INFO);
long time = 0L;
@ -287,7 +300,7 @@ public final class Compiler {
append(" ms ");
}
LOG.fine(sb);
log.fine(sb);
}
}
@ -305,14 +318,14 @@ public final class Compiler {
append(" ms");
}
LOG.info(sb);
log.info(sb);
}
return newFunctionNode;
}
private Class<?> install(final String className, final byte[] code) {
LOG.fine("Installing class ", className);
log.fine("Installing class ", className);
final Class<?> clazz = installer.install(Compiler.binaryName(className), code);
@ -384,7 +397,7 @@ public final class Compiler {
}
final StringBuilder sb;
if (LOG.isEnabled()) {
if (log.isEnabled()) {
sb = new StringBuilder();
sb.append("Installed class '").
append(rootClass.getSimpleName()).
@ -408,7 +421,7 @@ public final class Compiler {
}
if (sb != null) {
LOG.fine(sb);
log.fine(sb);
}
return rootClass;
@ -482,7 +495,7 @@ public final class Compiler {
private CompileUnit addCompileUnit(final String unitClassName, final long initialWeight) {
final CompileUnit compileUnit = initCompileUnit(unitClassName, initialWeight);
compileUnits.add(compileUnit);
LOG.fine("Added compile unit ", compileUnit);
log.fine("Added compile unit ", compileUnit);
return compileUnit;
}
@ -523,35 +536,4 @@ public final class Compiler {
return name.replace('/', '.');
}
/**
* Log hook; level finest
* @param args args
*/
public static void finest(final Object... args) {
LOG.finest(args);
}
/**
* Log hook; level fine
* @param args args
*/
public static void fine(final Object... args) {
LOG.fine(args);
}
/**
* Log hook; level info
* @param args args
*/
public static void info(final Object... args) {
LOG.info(args);
}
/**
* Log hook; level warning
* @param args args
*/
public static void warning(final Object... args) {
LOG.warning(args);
}
}

View File

@ -25,9 +25,6 @@
package jdk.nashorn.internal.codegen;
import static jdk.nashorn.internal.codegen.Compiler.info;
import static jdk.nashorn.internal.codegen.Compiler.warning;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
@ -39,7 +36,7 @@ import jdk.nashorn.internal.runtime.ScriptEnvironment;
* Class that facilitates dumping bytecode to disk
*/
final class DumpBytecode {
static void dumpBytecode(final ScriptEnvironment env, final byte[] bytecode, final String className) {
static void dumpBytecode(final ScriptEnvironment env, final Compiler compiler, final byte[] bytecode, final String className) {
File dir = null;
try {
// should could be printed to stderr for generate class?
@ -54,7 +51,7 @@ final class DumpBytecode {
if (env._print_code_dir != null) {
String name = className;
int dollar = name.lastIndexOf('$');
final int dollar = name.lastIndexOf('$');
if (dollar != -1) {
name = name.substring(dollar + 1);
}
@ -101,10 +98,10 @@ final class DumpBytecode {
try (final FileOutputStream fos = new FileOutputStream(file)) {
fos.write(bytecode);
}
info("Wrote class to '" + file.getAbsolutePath() + '\'');
compiler.getLogger().info("Wrote class to '" + file.getAbsolutePath() + '\'');
}
} catch (final IOException e) {
warning("Skipping class dump for ",
compiler.getLogger().warning("Skipping class dump for ",
className,
": ",
ECMAErrors.getMessage(

View File

@ -42,9 +42,12 @@ 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.DebugLogger;
import jdk.nashorn.internal.runtime.logging.DebugLogger;
import jdk.nashorn.internal.runtime.logging.Loggable;
import jdk.nashorn.internal.runtime.logging.Logger;
/**
* Lower to more primitive operations. After lowering, an AST has symbols and
@ -58,13 +61,24 @@ import jdk.nashorn.internal.runtime.DebugLogger;
* that scope and slot information is correct. This enables e.g. AccessSpecialization
* and frame optimizations
*/
@Logger(name="finalize")
final class FinalizeTypes extends NodeOperatorVisitor<LexicalContext> implements Loggable {
final class FinalizeTypes extends NodeOperatorVisitor<LexicalContext> {
private static final DebugLogger LOG = new DebugLogger("finalize");
private final DebugLogger log;
FinalizeTypes() {
super(new LexicalContext());
this.log = initLogger(Global.instance());
}
@Override
public DebugLogger getLogger() {
return log;
}
@Override
public DebugLogger initLogger(final Global global) {
return global.getLogger(this.getClass());
}
@Override
@ -176,13 +190,13 @@ final class FinalizeTypes extends NodeOperatorVisitor<LexicalContext> {
return functionNode.setState(lc, CompilationState.FINALIZED);
}
private static void updateSymbolsLog(final FunctionNode functionNode, final Symbol symbol, final boolean loseSlot) {
if (LOG.isEnabled()) {
private void updateSymbolsLog(final FunctionNode functionNode, final Symbol symbol, final boolean loseSlot) {
if (log.isEnabled()) {
if (!symbol.isScope()) {
LOG.finest("updateSymbols: ", symbol, " => scope, because all vars in ", functionNode.getName(), " are in scope");
log.finest("updateSymbols: ", symbol, " => scope, because all vars in ", functionNode.getName(), " are in scope");
}
if (loseSlot && symbol.hasSlot()) {
LOG.finest("updateSymbols: ", symbol, " => no slot, because all vars in ", functionNode.getName(), " are in scope");
log.finest("updateSymbols: ", symbol, " => no slot, because all vars in ", functionNode.getName(), " are in scope");
}
}
}

View File

@ -42,9 +42,12 @@ 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.runtime.DebugLogger;
import jdk.nashorn.internal.objects.Global;
import jdk.nashorn.internal.runtime.PropertyMap;
import jdk.nashorn.internal.runtime.RecompilableScriptFunctionData;
import jdk.nashorn.internal.runtime.logging.DebugLogger;
import jdk.nashorn.internal.runtime.logging.Loggable;
import jdk.nashorn.internal.runtime.logging.Logger;
/**
* Establishes depth of scope for non local symbols at the start of method.
@ -52,8 +55,8 @@ import jdk.nashorn.internal.runtime.RecompilableScriptFunctionData;
* stored in the RecompilableScriptFunctionData and is transferred to the
* FunctionNode being compiled
*/
final class FindScopeDepths extends NodeVisitor<LexicalContext> {
@Logger(name="scopedepths")
final class FindScopeDepths extends NodeVisitor<LexicalContext> implements Loggable {
private final Compiler compiler;
private final CompilationEnvironment env;
@ -61,12 +64,23 @@ final class FindScopeDepths extends NodeVisitor<LexicalContext> {
private final Map<Integer, Map<String, Integer>> externalSymbolDepths = new HashMap<>();
private final Map<Integer, Set<String>> internalSymbols = new HashMap<>();
private final static DebugLogger LOG = new DebugLogger("scopedepths");
private final DebugLogger log;
FindScopeDepths(final Compiler compiler) {
super(new LexicalContext());
this.compiler = compiler;
this.env = compiler.getCompilationEnvironment();
this.env = compiler.getCompilationEnvironment();
this.log = initLogger(Global.instance());
}
@Override
public DebugLogger getLogger() {
return log;
}
@Override
public DebugLogger initLogger(final Global global) {
return global.getLogger(this.getClass());
}
static int findScopesToStart(final LexicalContext lc, final FunctionNode fn, final Block block) {
@ -266,8 +280,8 @@ final class FindScopeDepths extends NodeVisitor<LexicalContext> {
addInternalSymbols(fn, internals.keySet());
if (LOG.isEnabled()) {
LOG.info(fn.getName() + " internals=" + internals + " externals=" + externalSymbolDepths.get(fn.getId()));
if (log.isEnabled()) {
log.info(fn.getName() + " internals=" + internals + " externals=" + externalSymbolDepths.get(fn.getId()));
}
return true;

View File

@ -27,6 +27,7 @@ package jdk.nashorn.internal.codegen;
import java.util.ArrayList;
import java.util.List;
import jdk.nashorn.internal.codegen.types.Type;
import jdk.nashorn.internal.ir.BinaryNode;
import jdk.nashorn.internal.ir.Block;
@ -44,26 +45,41 @@ 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.runtime.DebugLogger;
import jdk.nashorn.internal.objects.Global;
import jdk.nashorn.internal.runtime.JSType;
import jdk.nashorn.internal.runtime.ScriptRuntime;
import jdk.nashorn.internal.runtime.logging.DebugLogger;
import jdk.nashorn.internal.runtime.logging.Loggable;
import jdk.nashorn.internal.runtime.logging.Logger;
/**
* Simple constant folding pass, executed before IR is starting to be lowered.
*/
final class FoldConstants extends NodeVisitor<LexicalContext> {
@Logger(name="fold")
final class FoldConstants extends NodeVisitor<LexicalContext> implements Loggable {
private static final DebugLogger LOG = new DebugLogger("fold");
private final DebugLogger log;
FoldConstants() {
super(new LexicalContext());
this.log = initLogger(Global.instance());
}
@Override
public DebugLogger getLogger() {
return log;
}
@Override
public DebugLogger initLogger(final Global global) {
return global.getLogger(this.getClass());
}
@Override
public Node leaveUnaryNode(final UnaryNode unaryNode) {
final LiteralNode<?> literalNode = new UnaryNodeConstantEvaluator(unaryNode).eval();
if (literalNode != null) {
LOG.info("Unary constant folded ", unaryNode, " to ", literalNode);
log.info("Unary constant folded ", unaryNode, " to ", literalNode);
return literalNode;
}
return unaryNode;
@ -73,7 +89,7 @@ final class FoldConstants extends NodeVisitor<LexicalContext> {
public Node leaveBinaryNode(final BinaryNode binaryNode) {
final LiteralNode<?> literalNode = new BinaryNodeConstantEvaluator(binaryNode).eval();
if (literalNode != null) {
LOG.info("Binary constant folded ", binaryNode, " to ", literalNode);
log.info("Binary constant folded ", binaryNode, " to ", literalNode);
return literalNode;
}
return binaryNode;
@ -144,7 +160,7 @@ final class FoldConstants extends NodeVisitor<LexicalContext> {
final LexicalContext lc = new LexicalContext();
block.accept(lc, new NodeVisitor<LexicalContext>(lc) {
@Override
public boolean enterVarNode(VarNode varNode) {
public boolean enterVarNode(final VarNode varNode) {
statements.add(varNode.setInit(null));
return false;
}
@ -256,7 +272,7 @@ final class FoldConstants extends NodeVisitor<LexicalContext> {
break;
case ADD:
if ((lhs.isString() || rhs.isNumeric()) && (rhs.isString() || rhs.isNumeric())) {
Object res = ScriptRuntime.ADD(lhs.getObject(), rhs.getObject());
final Object res = ScriptRuntime.ADD(lhs.getObject(), rhs.getObject());
if (res instanceof Number) {
value = ((Number)res).doubleValue();
break;

View File

@ -34,6 +34,7 @@ import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.ListIterator;
import jdk.nashorn.internal.ir.BaseNode;
import jdk.nashorn.internal.ir.BinaryNode;
import jdk.nashorn.internal.ir.Block;
@ -67,12 +68,15 @@ 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.DebugLogger;
import jdk.nashorn.internal.runtime.ScriptRuntime;
import jdk.nashorn.internal.runtime.Source;
import jdk.nashorn.internal.runtime.logging.DebugLogger;
import jdk.nashorn.internal.runtime.logging.Loggable;
import jdk.nashorn.internal.runtime.logging.Logger;
/**
* Lower to more primitive operations. After lowering, an AST still has no symbols
@ -83,10 +87,10 @@ import jdk.nashorn.internal.runtime.Source;
* harder and context dependent to do any code copying after symbols have been
* finalized.
*/
@Logger(name="lower")
final class Lower extends NodeOperatorVisitor<BlockLexicalContext> implements Loggable {
final class Lower extends NodeOperatorVisitor<BlockLexicalContext> {
private static final DebugLogger LOG = new DebugLogger("lower");
private final DebugLogger log;
// needed only to get unique eval id
private final CodeInstaller<?> installer;
@ -137,7 +141,19 @@ final class Lower extends NodeOperatorVisitor<BlockLexicalContext> {
return block.setIsTerminal(this, false);
}
});
this.installer = installer;
this.log = initLogger(Global.instance());
}
@Override
public DebugLogger getLogger() {
return log;
}
@Override
public DebugLogger initLogger(final Global global) {
return global.getLogger(this.getClass());
}
@Override
@ -223,7 +239,7 @@ final class Lower extends NodeOperatorVisitor<BlockLexicalContext> {
}
@Override
public Node leaveBlockStatement(BlockStatement blockStatement) {
public Node leaveBlockStatement(final BlockStatement blockStatement) {
return addStatement(blockStatement);
}
@ -252,7 +268,7 @@ final class Lower extends NodeOperatorVisitor<BlockLexicalContext> {
@Override
public Node leaveFunctionNode(final FunctionNode functionNode) {
LOG.info("END FunctionNode: ", functionNode.getName());
log.info("END FunctionNode: ", functionNode.getName());
return functionNode.setState(lc, CompilationState.LOWERED);
}
@ -478,7 +494,7 @@ final class Lower extends NodeOperatorVisitor<BlockLexicalContext> {
if (tryNode.getCatchBlocks().isEmpty()) {
newTryNode = tryNode.setFinallyBody(null);
} else {
Block outerBody = new Block(tryNode.getToken(), tryNode.getFinish(), tryNode.setFinallyBody(null));
final Block outerBody = new Block(tryNode.getToken(), tryNode.getFinish(), tryNode.setFinallyBody(null));
newTryNode = tryNode.setBody(outerBody).setCatchBlocks(null);
}
@ -667,7 +683,7 @@ final class Lower extends NodeOperatorVisitor<BlockLexicalContext> {
* @return true if an assignment to eval result, false otherwise
*/
private static boolean isEvalResultAssignment(final Node expression) {
Node e = expression;
final Node e = expression;
assert e.tokenType() != TokenType.DISCARD; //there are no discards this early anymore
if (e instanceof BinaryNode) {
final Node lhs = ((BinaryNode)e).lhs();

View File

@ -98,12 +98,12 @@ import jdk.nashorn.internal.ir.Symbol;
import jdk.nashorn.internal.objects.Global;
import jdk.nashorn.internal.runtime.ArgumentSetter;
import jdk.nashorn.internal.runtime.Debug;
import jdk.nashorn.internal.runtime.DebugLogger;
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;
import jdk.nashorn.internal.runtime.options.Options;
/**
@ -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 static final DebugLogger LOG = new DebugLogger("codegen", "nashorn.codegen.debug");
private static final boolean DEBUG = LOG.isEnabled();
private final DebugLogger log = Global.instance().getLogger(CodeGenerator.class);
private final boolean debug = log.isEnabled();
/** dump stack on a particular line, or -1 if disabled */
private static final int DEBUG_TRACE_LINE;
@ -2301,7 +2301,7 @@ public class MethodEmitter implements Emitter {
* @param args debug information to print
*/
private void debug(final Object... args) {
if (DEBUG) {
if (debug) {
debug(30, args);
}
}
@ -2313,13 +2313,13 @@ public class MethodEmitter implements Emitter {
* @param args debug information to print
*/
private void debug_label(final Object... args) {
if (DEBUG) {
if (debug) {
debug(22, args);
}
}
private void debug(final int padConstant, final Object... args) {
if (DEBUG) {
if (debug) {
final StringBuilder sb = new StringBuilder();
int pad;
@ -2386,9 +2386,9 @@ public class MethodEmitter implements Emitter {
}
if (env != null) { //early bootstrap code doesn't have inited context yet
LOG.info(sb);
log.info(sb);
if (DEBUG_TRACE_LINE == linePrefix) {
new Throwable().printStackTrace(LOG.getOutputStream());
new Throwable().printStackTrace(log.getOutputStream());
}
}
}

View File

@ -50,30 +50,30 @@ import java.lang.invoke.MethodHandle;
import java.lang.invoke.MethodHandles;
import java.lang.invoke.MethodType;
import java.util.EnumSet;
import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Set;
import java.util.StringTokenizer;
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.DebugLogger;
import jdk.nashorn.internal.runtime.FunctionScope;
import jdk.nashorn.internal.runtime.PropertyMap;
import jdk.nashorn.internal.runtime.ScriptEnvironment;
import jdk.nashorn.internal.runtime.ScriptObject;
import jdk.nashorn.internal.runtime.Undefined;
import jdk.nashorn.internal.runtime.UnwarrantedOptimismException;
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;
/**
* Generates the ScriptObject subclass structure with fields for a user objects.
*/
public final class ObjectClassGenerator {
@Logger(name="fields")
public final class ObjectClassGenerator implements Loggable {
/**
* Type guard to make sure we don't unnecessarily explode field storages. Rather unbox e.g.
@ -96,44 +96,12 @@ public final class ObjectClassGenerator {
* Debug field logger
* Should we print debugging information for fields when they are generated and getters/setters are called?
*/
private static final DebugLogger LOG = new DebugLogger("fields", "nashorn.fields.debug");
private final DebugLogger log;
/**
* Get the field logger
* @return logger
*/
public static DebugLogger getLogger() {
return LOG;
}
private static final Set<String> FIELDS_TO_INSTRUMENT;
static {
final String fields = Options.getStringProperty("nashorn.fields", null);
final Set<String> fti = new HashSet<>();
if (fields != null) {
final StringTokenizer st = new StringTokenizer(fields, ",");
while (st.hasMoreTokens()) {
fti.add(st.nextToken());
}
}
FIELDS_TO_INSTRUMENT = fti.isEmpty() ? null : fti;
}
/**
* Should this particular field be instrumented with --log=fields
* Internal use only
* @param field field name
* @return true if it should be instrumented
*/
public static boolean shouldInstrument(final String field) {
//if no explicit fields to imstrument are given, instrument all fields
return FIELDS_TO_INSTRUMENT == null || FIELDS_TO_INSTRUMENT.contains(field);
}
/**
* is field debugging enabled. Several modules in codegen and properties use this, hence
* public access.
*/
public static final boolean DEBUG_FIELDS = LOG.isEnabled();
private static final boolean EXPLICIT_OBJECT = Options.getBooleanProperty("nashorn.fields.objects");
@ -163,11 +131,10 @@ public final class ObjectClassGenerator {
static {
if (!OBJECT_FIELDS_ONLY) {
FIELD_TYPES.add(PRIMITIVE_FIELD_TYPE);
} else {
LOG.warning("Running with object fields only - this is a deprecated configuration.");
}
FIELD_TYPES.add(Type.OBJECT);
}
private static boolean initialized = false;
/** The context */
private final Context context;
@ -180,6 +147,25 @@ public final class ObjectClassGenerator {
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.");
}
}
}
}
@Override
public DebugLogger getLogger() {
return log;
}
@Override
public DebugLogger initLogger(final Global global) {
return global.getLogger(this.getClass());
}
/**

View File

@ -47,8 +47,11 @@ 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.DebugLogger;
import jdk.nashorn.internal.runtime.logging.DebugLogger;
import jdk.nashorn.internal.runtime.logging.Loggable;
import jdk.nashorn.internal.runtime.logging.Logger;
/**
* Range analysis and narrowing of type where it can be proven
@ -63,15 +66,28 @@ import jdk.nashorn.internal.runtime.DebugLogger;
*
* Proves that the multiplication never exceeds 24 bits and can thus be an int
*/
final class RangeAnalyzer extends NodeOperatorVisitor<LexicalContext> {
static final DebugLogger LOG = new DebugLogger("ranges");
@Logger(name="ranges")
final class RangeAnalyzer extends NodeOperatorVisitor<LexicalContext> implements Loggable {
private final DebugLogger log;
private static final Range.Functionality RANGE = new Range.Functionality(LOG);
private final Range.Functionality func;
private final Map<LoopNode, Symbol> loopCounters = new HashMap<>();
RangeAnalyzer() {
super(new LexicalContext());
this.log = initLogger(Global.instance());
this.func = new Range.Functionality(log);
}
@Override
public DebugLogger getLogger() {
return log;
}
@Override
public DebugLogger initLogger(final Global global) {
return global.getLogger(this.getClass());
}
@Override
@ -80,7 +96,7 @@ final class RangeAnalyzer extends NodeOperatorVisitor<LexicalContext> {
//properly identified and that no optimizations can be made with it - its range is
//simply unknown in that case, if it is assigned in the loop
final Symbol counter = findLoopCounter(forNode);
LOG.fine("Entering forNode " + forNode + " counter = " + counter);
log.fine("Entering forNode " + forNode + " counter = " + counter);
if (counter != null && !assignedInLoop(forNode, counter)) {
loopCounters.put(forNode, counter);
}
@ -96,7 +112,7 @@ final class RangeAnalyzer extends NodeOperatorVisitor<LexicalContext> {
final Symbol symbol = dest.getSymbol();
assert symbol != null : dest + " " + dest.getClass() + " has no symbol";
assert symbol.getRange() != null : symbol + " has no range";
final Range symRange = RANGE.join(symbol.getRange(), range);
final Range symRange = func.join(symbol.getRange(), range);
//anything assigned in the loop, not being the safe loop counter(s) invalidates its entire range
if (lc.inLoop() && !isLoopCounter(lc.getCurrentLoop(), symbol)) {
@ -105,7 +121,7 @@ final class RangeAnalyzer extends NodeOperatorVisitor<LexicalContext> {
}
if (!symRange.equals(symbol.getRange())) {
LOG.fine("Modify range for " + dest + " " + symbol + " from " + symbol.getRange() + " to " + symRange + " (in node = " + dest + ")" );
log.fine("Modify range for " + dest + " " + symbol + " from " + symbol.getRange() + " to " + symRange + " (in node = " + dest + ")" );
symbol.setRange(symRange);
}
@ -114,67 +130,67 @@ final class RangeAnalyzer extends NodeOperatorVisitor<LexicalContext> {
@Override
public Node leaveADD(final BinaryNode node) {
setRange(node, RANGE.add(node.lhs().getSymbol().getRange(), node.rhs().getSymbol().getRange()));
setRange(node, func.add(node.lhs().getSymbol().getRange(), node.rhs().getSymbol().getRange()));
return node;
}
@Override
public Node leaveSUB(final BinaryNode node) {
setRange(node, RANGE.sub(node.lhs().getSymbol().getRange(), node.rhs().getSymbol().getRange()));
setRange(node, func.sub(node.lhs().getSymbol().getRange(), node.rhs().getSymbol().getRange()));
return node;
}
@Override
public Node leaveMUL(final BinaryNode node) {
setRange(node, RANGE.mul(node.lhs().getSymbol().getRange(), node.rhs().getSymbol().getRange()));
setRange(node, func.mul(node.lhs().getSymbol().getRange(), node.rhs().getSymbol().getRange()));
return node;
}
@Override
public Node leaveDIV(final BinaryNode node) {
setRange(node, RANGE.div(node.lhs().getSymbol().getRange(), node.rhs().getSymbol().getRange()));
setRange(node, func.div(node.lhs().getSymbol().getRange(), node.rhs().getSymbol().getRange()));
return node;
}
@Override
public Node leaveMOD(final BinaryNode node) {
setRange(node, RANGE.mod(node.lhs().getSymbol().getRange(), node.rhs().getSymbol().getRange()));
setRange(node, func.mod(node.lhs().getSymbol().getRange(), node.rhs().getSymbol().getRange()));
return node;
}
@Override
public Node leaveBIT_AND(final BinaryNode node) {
setRange(node, RANGE.and(node.lhs().getSymbol().getRange(), node.rhs().getSymbol().getRange()));
setRange(node, func.and(node.lhs().getSymbol().getRange(), node.rhs().getSymbol().getRange()));
return node;
}
@Override
public Node leaveBIT_OR(final BinaryNode node) {
setRange(node, RANGE.or(node.lhs().getSymbol().getRange(), node.rhs().getSymbol().getRange()));
setRange(node, func.or(node.lhs().getSymbol().getRange(), node.rhs().getSymbol().getRange()));
return node;
}
@Override
public Node leaveBIT_XOR(final BinaryNode node) {
setRange(node, RANGE.xor(node.lhs().getSymbol().getRange(), node.rhs().getSymbol().getRange()));
setRange(node, func.xor(node.lhs().getSymbol().getRange(), node.rhs().getSymbol().getRange()));
return node;
}
@Override
public Node leaveSAR(final BinaryNode node) {
setRange(node, RANGE.sar(node.lhs().getSymbol().getRange(), node.rhs().getSymbol().getRange()));
setRange(node, func.sar(node.lhs().getSymbol().getRange(), node.rhs().getSymbol().getRange()));
return node;
}
@Override
public Node leaveSHL(final BinaryNode node) {
setRange(node, RANGE.shl(node.lhs().getSymbol().getRange(), node.rhs().getSymbol().getRange()));
setRange(node, func.shl(node.lhs().getSymbol().getRange(), node.rhs().getSymbol().getRange()));
return node;
}
@Override
public Node leaveSHR(final BinaryNode node) {
setRange(node, RANGE.shr(node.lhs().getSymbol().getRange(), node.rhs().getSymbol().getRange()));
setRange(node, func.shr(node.lhs().getSymbol().getRange(), node.rhs().getSymbol().getRange()));
return node;
}
@ -250,17 +266,17 @@ final class RangeAnalyzer extends NodeOperatorVisitor<LexicalContext> {
@Override
public Node leaveASSIGN_ADD(final BinaryNode node) {
return leaveSelfModifyingAssign(node, RANGE.add(node.lhs().getSymbol().getRange(), node.rhs().getSymbol().getRange()));
return leaveSelfModifyingAssign(node, func.add(node.lhs().getSymbol().getRange(), node.rhs().getSymbol().getRange()));
}
@Override
public Node leaveASSIGN_SUB(final BinaryNode node) {
return leaveSelfModifyingAssign(node, RANGE.sub(node.lhs().getSymbol().getRange(), node.rhs().getSymbol().getRange()));
return leaveSelfModifyingAssign(node, func.sub(node.lhs().getSymbol().getRange(), node.rhs().getSymbol().getRange()));
}
@Override
public Node leaveASSIGN_MUL(final BinaryNode node) {
return leaveSelfModifyingAssign(node, RANGE.mul(node.lhs().getSymbol().getRange(), node.rhs().getSymbol().getRange()));
return leaveSelfModifyingAssign(node, func.mul(node.lhs().getSymbol().getRange(), node.rhs().getSymbol().getRange()));
}
@Override
@ -275,32 +291,32 @@ final class RangeAnalyzer extends NodeOperatorVisitor<LexicalContext> {
@Override
public Node leaveASSIGN_BIT_AND(final BinaryNode node) {
return leaveSelfModifyingAssign(node, RANGE.and(node.lhs().getSymbol().getRange(), node.rhs().getSymbol().getRange()));
return leaveSelfModifyingAssign(node, func.and(node.lhs().getSymbol().getRange(), node.rhs().getSymbol().getRange()));
}
@Override
public Node leaveASSIGN_BIT_OR(final BinaryNode node) {
return leaveSelfModifyingAssign(node, RANGE.or(node.lhs().getSymbol().getRange(), node.rhs().getSymbol().getRange()));
return leaveSelfModifyingAssign(node, func.or(node.lhs().getSymbol().getRange(), node.rhs().getSymbol().getRange()));
}
@Override
public Node leaveASSIGN_BIT_XOR(final BinaryNode node) {
return leaveSelfModifyingAssign(node, RANGE.xor(node.lhs().getSymbol().getRange(), node.rhs().getSymbol().getRange()));
return leaveSelfModifyingAssign(node, func.xor(node.lhs().getSymbol().getRange(), node.rhs().getSymbol().getRange()));
}
@Override
public Node leaveASSIGN_SAR(final BinaryNode node) {
return leaveSelfModifyingAssign(node, RANGE.sar(node.lhs().getSymbol().getRange(), node.rhs().getSymbol().getRange()));
return leaveSelfModifyingAssign(node, func.sar(node.lhs().getSymbol().getRange(), node.rhs().getSymbol().getRange()));
}
@Override
public Node leaveASSIGN_SHR(final BinaryNode node) {
return leaveSelfModifyingAssign(node, RANGE.shr(node.lhs().getSymbol().getRange(), node.rhs().getSymbol().getRange()));
return leaveSelfModifyingAssign(node, func.shr(node.lhs().getSymbol().getRange(), node.rhs().getSymbol().getRange()));
}
@Override
public Node leaveASSIGN_SHL(final BinaryNode node) {
return leaveSelfModifyingAssign(node, RANGE.shl(node.lhs().getSymbol().getRange(), node.rhs().getSymbol().getRange()));
return leaveSelfModifyingAssign(node, func.shl(node.lhs().getSymbol().getRange(), node.rhs().getSymbol().getRange()));
}
@Override
@ -308,10 +324,10 @@ final class RangeAnalyzer extends NodeOperatorVisitor<LexicalContext> {
switch (node.tokenType()) {
case DECPREFIX:
case DECPOSTFIX:
return leaveSelfModifyingAssign(node, RANGE.sub(node.getExpression().getSymbol().getRange(), Range.createRange(1)));
return leaveSelfModifyingAssign(node, func.sub(node.getExpression().getSymbol().getRange(), Range.createRange(1)));
case INCPREFIX:
case INCPOSTFIX:
return leaveSelfModifyingAssign(node, RANGE.add(node.getExpression().getSymbol().getRange(), Range.createRange(1)));
return leaveSelfModifyingAssign(node, func.add(node.getExpression().getSymbol().getRange(), Range.createRange(1)));
default:
throw new UnsupportedOperationException("" + node.tokenType());
}
@ -341,7 +357,7 @@ final class RangeAnalyzer extends NodeOperatorVisitor<LexicalContext> {
@Override
public Node leaveSUB(final UnaryNode node) {
setRange(node, RANGE.neg(node.getExpression().getSymbol().getRange()));
setRange(node, func.neg(node.getExpression().getSymbol().getRange()));
return node;
}
@ -436,7 +452,7 @@ final class RangeAnalyzer extends NodeOperatorVisitor<LexicalContext> {
* @param node loop node to check
* @return
*/
private static Symbol findLoopCounter(final LoopNode node) {
private Symbol findLoopCounter(final LoopNode node) {
final Expression test = node.getTest();
if (test != null && test.isComparison()) {
@ -453,7 +469,7 @@ final class RangeAnalyzer extends NodeOperatorVisitor<LexicalContext> {
switch (op) {
case LT:
case LE:
symbol.setRange(RANGE.join(symbol.getRange(), Range.createRange(op == TokenType.LT ? margin - 1 : margin)));
symbol.setRange(func.join(symbol.getRange(), Range.createRange(op == TokenType.LT ? margin - 1 : margin)));
return symbol;
case GT:
case GE:

View File

@ -26,12 +26,12 @@
package jdk.nashorn.internal.codegen;
import static jdk.nashorn.internal.codegen.CompilerConstants.SPLIT_PREFIX;
import static jdk.nashorn.internal.codegen.Compiler.finest;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import jdk.nashorn.internal.ir.Block;
import jdk.nashorn.internal.ir.FunctionNode;
import jdk.nashorn.internal.ir.FunctionNode.CompilationState;
@ -43,6 +43,7 @@ import jdk.nashorn.internal.ir.Node;
import jdk.nashorn.internal.ir.SplitNode;
import jdk.nashorn.internal.ir.Statement;
import jdk.nashorn.internal.ir.visitor.NodeVisitor;
import jdk.nashorn.internal.runtime.logging.DebugLogger;
import jdk.nashorn.internal.runtime.options.Options;
/**
@ -64,6 +65,8 @@ final class Splitter extends NodeVisitor<LexicalContext> {
/** Weight threshold for when to start a split. */
public static final long SPLIT_THRESHOLD = Options.getIntProperty("nashorn.compiler.splitter.threshold", 32 * 1024);
private final DebugLogger log;
/**
* Constructor.
*
@ -76,6 +79,7 @@ final class Splitter extends NodeVisitor<LexicalContext> {
this.compiler = compiler;
this.outermost = functionNode;
this.outermostCompileUnit = outermostCompileUnit;
this.log = compiler.getLogger();
}
/**
@ -86,7 +90,7 @@ final class Splitter extends NodeVisitor<LexicalContext> {
FunctionNode split(final FunctionNode fn, final boolean top) {
FunctionNode functionNode = fn;
finest("Initiating split of '", functionNode.getName(), "'");
log.finest("Initiating split of '", functionNode.getName(), "'");
long weight = WeighNodes.weigh(functionNode);
@ -95,7 +99,7 @@ final class Splitter extends NodeVisitor<LexicalContext> {
assert lc.isEmpty() : "LexicalContext not empty";
if (weight >= SPLIT_THRESHOLD) {
finest("Splitting '", functionNode.getName(), "' as its weight ", weight, " exceeds split threshold ", SPLIT_THRESHOLD);
log.finest("Splitting '", functionNode.getName(), "' as its weight ", weight, " exceeds split threshold ", SPLIT_THRESHOLD);
functionNode = (FunctionNode)functionNode.accept(this);
if (functionNode.isSplit()) {

View File

@ -29,7 +29,7 @@ import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import jdk.nashorn.internal.runtime.DebugLogger;
import jdk.nashorn.internal.runtime.logging.DebugLogger;
import jdk.nashorn.internal.runtime.JSType;
/**
@ -544,8 +544,8 @@ public abstract class Range {
final long shift = ((IntegerRange) b).getMin() & 0x1f;
final IntegerRange left = (IntegerRange)(a.isIntegerType() ? a : createTypeRange(Type.INT));
if (left.getMin() >= 0) {
long min = left.getMin() >>> shift;
long max = left.getMax() >>> shift;
final long min = left.getMin() >>> shift;
final long max = left.getMax() >>> shift;
return createIntegerRange(min, max);
} else if (shift >= 1) {
return createIntegerRange(0, JSType.MAX_UINT >>> shift);

View File

@ -28,9 +28,6 @@ package jdk.nashorn.internal.ir;
import static jdk.nashorn.internal.codegen.CompilerConstants.__DIR__;
import static jdk.nashorn.internal.codegen.CompilerConstants.__FILE__;
import static jdk.nashorn.internal.codegen.CompilerConstants.__LINE__;
import static jdk.nashorn.internal.codegen.ObjectClassGenerator.DEBUG_FIELDS;
import jdk.nashorn.internal.codegen.ObjectClassGenerator;
import jdk.nashorn.internal.codegen.types.Type;
import jdk.nashorn.internal.ir.annotations.Immutable;
import jdk.nashorn.internal.ir.visitor.NodeVisitor;
@ -219,9 +216,6 @@ public final class IdentNode extends Expression implements PropertyKey, Function
if (this.optimisticType == callSiteType) {
return this;
}
if (DEBUG_FIELDS && ObjectClassGenerator.shouldInstrument(getName()) && getSymbol() != null && !Type.areEquivalent(getSymbol().getSymbolType(), callSiteType)) {
ObjectClassGenerator.getLogger().info(getClass().getName(), " ", this, " => ", callSiteType, " instead of ", getType());
}
return new IdentNode(this, name, callSiteType, flags, programPoint);
}

View File

@ -37,9 +37,12 @@ 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.Debug;
import jdk.nashorn.internal.runtime.DebugLogger;
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.ScriptObject;
import jdk.nashorn.internal.runtime.options.Options;
@ -97,38 +100,20 @@ public final class MethodHandleFactory {
return obj.toString();
}
private static final MethodHandleFunctionality STANDARD = new StandardMethodHandleFunctionality();
private static final MethodHandleFunctionality FUNC;
private static final String DEBUG_PROPERTY = "nashorn.methodhandles.debug";
private static final DebugLogger LOG = new DebugLogger("methodhandles", DEBUG_PROPERTY);
static {
if (LOG.isEnabled() || Options.getBooleanProperty(DEBUG_PROPERTY)) {
if (Options.getStringProperty(DEBUG_PROPERTY, "").equals("create")) {
FUNC = new TraceCreateMethodHandleFunctionality();
} else {
FUNC = new TraceMethodHandleFunctionality();
}
} else {
FUNC = STANDARD;
}
}
private static final MethodHandleFunctionality FUNC = new StandardMethodHandleFunctionality();
private static final boolean PRINT_STACKTRACE = Options.getBooleanProperty("nashorn.methodhandles.debug.stacktrace");
/**
* Return the method handle functionality used for all method handle operations
* @return a method handle functionality implementation
*/
public static MethodHandleFunctionality getFunctionality() {
public static synchronized MethodHandleFunctionality getFunctionality() {
return FUNC;
}
private static final MethodHandle TRACE = STANDARD.findStatic(LOOKUP, MethodHandleFactory.class, "traceArgs", MethodType.methodType(void.class, DebugLogger.class, String.class, int.class, Object[].class));
private static final MethodHandle TRACE_RETURN = STANDARD.findStatic(LOOKUP, MethodHandleFactory.class, "traceReturn", MethodType.methodType(Object.class, DebugLogger.class, Object.class));
private static final MethodHandle TRACE_RETURN_VOID = STANDARD.findStatic(LOOKUP, MethodHandleFactory.class, "traceReturnVoid", MethodType.methodType(void.class, DebugLogger.class));
private static final MethodHandle TRACE = FUNC.findStatic(LOOKUP, MethodHandleFactory.class, "traceArgs", MethodType.methodType(void.class, DebugLogger.class, String.class, int.class, Object[].class));
private static final MethodHandle TRACE_RETURN = FUNC.findStatic(LOOKUP, MethodHandleFactory.class, "traceReturn", MethodType.methodType(Object.class, DebugLogger.class, Object.class));
private static final MethodHandle TRACE_RETURN_VOID = FUNC.findStatic(LOOKUP, MethodHandleFactory.class, "traceReturnVoid", MethodType.methodType(void.class, DebugLogger.class));
private static final String VOID_TAG = "[VOID]";
@ -234,7 +219,6 @@ public final class MethodHandleFactory {
return addDebugPrintout(logger, level, mh, 0, true, tag);
}
/**
* Add a debug printout to a method handle, tracing parameters and return values
*
@ -283,194 +267,34 @@ public final class MethodHandleFactory {
}
/**
* The standard class that marshalls all method handle operations to the java.lang.invoke
* Class that marshalls all method handle operations to the java.lang.invoke
* package. This exists only so that it can be subclassed and method handles created from
* Nashorn made possible to instrument.
*
* All Nashorn classes should use the MethodHandleFactory for their method handle operations
*/
private static class StandardMethodHandleFunctionality implements MethodHandleFunctionality {
@Logger(name="methodhandles")
private static class StandardMethodHandleFunctionality implements MethodHandleFunctionality, Loggable {
@Override
public MethodHandle filterArguments(final MethodHandle target, final int pos, final MethodHandle... filters) {
return MethodHandles.filterArguments(target, pos, filters);
// for bootstrapping reasons, because a lot of static fields use MH for lookups, we
// need to set the logger when the Global object is finished. This means that we don't
// get instrumentation for public static final MethodHandle SOMETHING = MH... in the builtin
// classes, but that doesn't matter, because this is usually not where we want it
private DebugLogger log = DebugLogger.DISABLED_LOGGER;
public StandardMethodHandleFunctionality() {
}
@Override
public MethodHandle filterReturnValue(final MethodHandle target, final MethodHandle filter) {
return MethodHandles.filterReturnValue(target, filter);
public DebugLogger initLogger(final Global global) {
return this.log = global.getLogger(this.getClass());
}
@Override
public MethodHandle guardWithTest(final MethodHandle test, final MethodHandle target, final MethodHandle fallback) {
return MethodHandles.guardWithTest(test, target, fallback);
public DebugLogger getLogger() {
return log;
}
@Override
public MethodHandle insertArguments(final MethodHandle target, final int pos, final Object... values) {
return MethodHandles.insertArguments(target, pos, values);
}
@Override
public MethodHandle dropArguments(final MethodHandle target, final int pos, final Class<?>... valueTypes) {
return MethodHandles.dropArguments(target, pos, valueTypes);
}
@Override
public MethodHandle dropArguments(final MethodHandle target, final int pos, final List<Class<?>> valueTypes) {
return MethodHandles.dropArguments(target, pos, valueTypes);
}
@Override
public MethodHandle asType(final MethodHandle handle, final MethodType type) {
return handle.asType(type);
}
@Override
public MethodHandle bindTo(final MethodHandle handle, final Object x) {
return handle.bindTo(x);
}
@Override
public MethodHandle foldArguments(final MethodHandle target, final MethodHandle combiner) {
return MethodHandles.foldArguments(target, combiner);
}
@Override
public MethodHandle explicitCastArguments(final MethodHandle target, final MethodType type) {
return MethodHandles.explicitCastArguments(target, type);
}
@Override
public MethodHandle arrayElementGetter(final Class<?> type) {
return MethodHandles.arrayElementGetter(type);
}
@Override
public MethodHandle arrayElementSetter(final Class<?> type) {
return MethodHandles.arrayElementSetter(type);
}
@Override
public MethodHandle throwException(final Class<?> returnType, final Class<? extends Throwable> exType) {
return MethodHandles.throwException(returnType, exType);
}
@Override
public MethodHandle catchException(final MethodHandle target, final Class<? extends Throwable> exType, final MethodHandle handler) {
return MethodHandles.catchException(target, exType, handler);
}
@Override
public MethodHandle constant(final Class<?> type, final Object value) {
return MethodHandles.constant(type, value);
}
@Override
public MethodHandle asCollector(final MethodHandle handle, final Class<?> arrayType, final int arrayLength) {
return handle.asCollector(arrayType, arrayLength);
}
@Override
public MethodHandle asSpreader(final MethodHandle handle, final Class<?> arrayType, final int arrayLength) {
return handle.asSpreader(arrayType, arrayLength);
}
@Override
public MethodHandle getter(final MethodHandles.Lookup explicitLookup, final Class<?> clazz, final String name, final Class<?> type) {
try {
return explicitLookup.findGetter(clazz, name, type);
} catch (final NoSuchFieldException | IllegalAccessException e) {
throw new LookupException(e);
}
}
@Override
public MethodHandle staticGetter(final MethodHandles.Lookup explicitLookup, final Class<?> clazz, final String name, final Class<?> type) {
try {
return explicitLookup.findStaticGetter(clazz, name, type);
} catch (final NoSuchFieldException | IllegalAccessException e) {
throw new LookupException(e);
}
}
@Override
public MethodHandle setter(final MethodHandles.Lookup explicitLookup, final Class<?> clazz, final String name, final Class<?> type) {
try {
return explicitLookup.findSetter(clazz, name, type);
} catch (final NoSuchFieldException | IllegalAccessException e) {
throw new LookupException(e);
}
}
@Override
public MethodHandle staticSetter(final MethodHandles.Lookup explicitLookup, final Class<?> clazz, final String name, final Class<?> type) {
try {
return explicitLookup.findStaticSetter(clazz, name, type);
} catch (final NoSuchFieldException | IllegalAccessException e) {
throw new LookupException(e);
}
}
@Override
public MethodHandle find(final Method method) {
try {
return PUBLIC_LOOKUP.unreflect(method);
} catch (final IllegalAccessException e) {
throw new LookupException(e);
}
}
@Override
public MethodHandle findStatic(final MethodHandles.Lookup explicitLookup, final Class<?> clazz, final String name, final MethodType type) {
try {
return explicitLookup.findStatic(clazz, name, type);
} catch (final NoSuchMethodException | IllegalAccessException e) {
throw new LookupException(e);
}
}
@Override
public MethodHandle findSpecial(final MethodHandles.Lookup explicitLookup, final Class<?> clazz, final String name, final MethodType type, final Class<?> thisClass) {
try {
return explicitLookup.findSpecial(clazz, name, type, thisClass);
} catch (final NoSuchMethodException | IllegalAccessException e) {
throw new LookupException(e);
}
}
@Override
public MethodHandle findVirtual(final MethodHandles.Lookup explicitLookup, final Class<?> clazz, final String name, final MethodType type) {
try {
return explicitLookup.findVirtual(clazz, name, type);
} catch (final NoSuchMethodException | IllegalAccessException e) {
throw new LookupException(e);
}
}
@Override
public SwitchPoint createSwitchPoint() {
return new SwitchPoint();
}
@Override
public MethodHandle guardWithTest(final SwitchPoint sp, final MethodHandle before, final MethodHandle after) {
return sp.guardWithTest(before, after);
}
@Override
public MethodType type(final Class<?> returnType, final Class<?>... paramTypes) {
return MethodType.methodType(returnType, paramTypes);
}
}
/**
* Class used for instrumenting and debugging Nashorn generated method handles
*/
private static class TraceMethodHandleFunctionality extends StandardMethodHandleFunctionality {
protected static String describe(final Object... data) {
final StringBuilder sb = new StringBuilder();
@ -503,183 +327,215 @@ public final class MethodHandleFactory {
}
public MethodHandle debug(final MethodHandle master, final String str, final Object... args) {
return addDebugPrintout(LOG, Level.INFO, master, Integer.MAX_VALUE, false, str + ' ' + describe(args));
if (log.isEnabled()) {
if (PRINT_STACKTRACE) {
stacktrace(log);
}
return addDebugPrintout(log, Level.INFO, master, Integer.MAX_VALUE, false, str + ' ' + describe(args));
}
return master;
}
@Override
public MethodHandle filterArguments(final MethodHandle target, final int pos, final MethodHandle... filters) {
final MethodHandle mh = super.filterArguments(target, pos, filters);
final MethodHandle mh = MethodHandles.filterArguments(target, pos, filters);
return debug(mh, "filterArguments", target, pos, filters);
}
@Override
public MethodHandle filterReturnValue(final MethodHandle target, final MethodHandle filter) {
final MethodHandle mh = super.filterReturnValue(target, filter);
final MethodHandle mh = MethodHandles.filterReturnValue(target, filter);
return debug(mh, "filterReturnValue", target, filter);
}
@Override
public MethodHandle guardWithTest(final MethodHandle test, final MethodHandle target, final MethodHandle fallback) {
final MethodHandle mh = super.guardWithTest(test, target, fallback);
final MethodHandle mh = MethodHandles.guardWithTest(test, target, fallback);
return debug(mh, "guardWithTest", test, target, fallback);
}
@Override
public MethodHandle insertArguments(final MethodHandle target, final int pos, final Object... values) {
final MethodHandle mh = super.insertArguments(target, pos, values);
final MethodHandle mh = MethodHandles.insertArguments(target, pos, values);
return debug(mh, "insertArguments", target, pos, values);
}
@Override
public MethodHandle dropArguments(final MethodHandle target, final int pos, final Class<?>... values) {
final MethodHandle mh = super.dropArguments(target, pos, values);
final MethodHandle mh = MethodHandles.dropArguments(target, pos, values);
return debug(mh, "dropArguments", target, pos, values);
}
@Override
public MethodHandle dropArguments(final MethodHandle target, final int pos, final List<Class<?>> values) {
final MethodHandle mh = super.dropArguments(target, pos, values);
final MethodHandle mh = MethodHandles.dropArguments(target, pos, values);
return debug(mh, "dropArguments", target, pos, values);
}
@Override
public MethodHandle asType(final MethodHandle handle, final MethodType type) {
final MethodHandle mh = super.asType(handle, type);
final MethodHandle mh = handle.asType(type);
return debug(mh, "asType", handle, type);
}
@Override
public MethodHandle bindTo(final MethodHandle handle, final Object x) {
final MethodHandle mh = super.bindTo(handle, x);
final MethodHandle mh = handle.bindTo(x);
return debug(mh, "bindTo", handle, x);
}
@Override
public MethodHandle foldArguments(final MethodHandle target, final MethodHandle combiner) {
final MethodHandle mh = super.foldArguments(target, combiner);
final MethodHandle mh = MethodHandles.foldArguments(target, combiner);
return debug(mh, "foldArguments", target, combiner);
}
@Override
public MethodHandle explicitCastArguments(final MethodHandle target, final MethodType type) {
final MethodHandle mh = super.explicitCastArguments(target, type);
final MethodHandle mh = MethodHandles.explicitCastArguments(target, type);
return debug(mh, "explicitCastArguments", target, type);
}
@Override
public MethodHandle arrayElementGetter(final Class<?> type) {
final MethodHandle mh = super.arrayElementGetter(type);
final MethodHandle mh = MethodHandles.arrayElementGetter(type);
return debug(mh, "arrayElementGetter", type);
}
@Override
public MethodHandle arrayElementSetter(final Class<?> type) {
final MethodHandle mh = super.arrayElementSetter(type);
final MethodHandle mh = MethodHandles.arrayElementSetter(type);
return debug(mh, "arrayElementSetter", type);
}
@Override
public MethodHandle throwException(final Class<?> returnType, final Class<? extends Throwable> exType) {
final MethodHandle mh = super.throwException(returnType, exType);
final MethodHandle mh = MethodHandles.throwException(returnType, exType);
return debug(mh, "throwException", returnType, exType);
}
@Override
public MethodHandle catchException(final MethodHandle target, final Class<? extends Throwable> exType, final MethodHandle handler) {
final MethodHandle mh = super.catchException(target, exType, handler);
final MethodHandle mh = MethodHandles.catchException(target, exType, handler);
return debug(mh, "catchException", exType);
}
@Override
public MethodHandle constant(final Class<?> type, final Object value) {
final MethodHandle mh = super.constant(type, value);
final MethodHandle mh = MethodHandles.constant(type, value);
return debug(mh, "constant", type, value);
}
@Override
public MethodHandle asCollector(final MethodHandle handle, final Class<?> arrayType, final int arrayLength) {
final MethodHandle mh = super.asCollector(handle, arrayType, arrayLength);
final MethodHandle mh = handle.asCollector(arrayType, arrayLength);
return debug(mh, "asCollector", handle, arrayType, arrayLength);
}
@Override
public MethodHandle asSpreader(final MethodHandle handle, final Class<?> arrayType, final int arrayLength) {
final MethodHandle mh = super.asSpreader(handle, arrayType, arrayLength);
final MethodHandle mh = handle.asSpreader(arrayType, arrayLength);
return debug(mh, "asSpreader", handle, arrayType, arrayLength);
}
@Override
public MethodHandle getter(final MethodHandles.Lookup explicitLookup, final Class<?> clazz, final String name, final Class<?> type) {
final MethodHandle mh = super.getter(explicitLookup, clazz, name, type);
return debug(mh, "getter", explicitLookup, clazz, name, type);
try {
final MethodHandle mh = explicitLookup.findGetter(clazz, name, type);
return debug(mh, "getter", explicitLookup, clazz, name, type);
} catch (final NoSuchFieldException | IllegalAccessException e) {
throw new LookupException(e);
}
}
@Override
public MethodHandle staticGetter(final MethodHandles.Lookup explicitLookup, final Class<?> clazz, final String name, final Class<?> type) {
final MethodHandle mh = super.staticGetter(explicitLookup, clazz, name, type);
return debug(mh, "static getter", explicitLookup, clazz, name, type);
try {
final MethodHandle mh = explicitLookup.findStaticGetter(clazz, name, type);
return debug(mh, "static getter", explicitLookup, clazz, name, type);
} catch (final NoSuchFieldException | IllegalAccessException e) {
throw new LookupException(e);
}
}
@Override
public MethodHandle setter(final MethodHandles.Lookup explicitLookup, final Class<?> clazz, final String name, final Class<?> type) {
final MethodHandle mh = super.setter(explicitLookup, clazz, name, type);
return debug(mh, "setter", explicitLookup, clazz, name, type);
try {
final MethodHandle mh = explicitLookup.findSetter(clazz, name, type);
return debug(mh, "setter", explicitLookup, clazz, name, type);
} catch (final NoSuchFieldException | IllegalAccessException e) {
throw new LookupException(e);
}
}
@Override
public MethodHandle staticSetter(final MethodHandles.Lookup explicitLookup, final Class<?> clazz, final String name, final Class<?> type) {
final MethodHandle mh = super.staticSetter(explicitLookup, clazz, name, type);
return debug(mh, "static setter", explicitLookup, clazz, name, type);
try {
final MethodHandle mh = explicitLookup.findStaticSetter(clazz, name, type);
return debug(mh, "static setter", explicitLookup, clazz, name, type);
} catch (final NoSuchFieldException | IllegalAccessException e) {
throw new LookupException(e);
}
}
@Override
public MethodHandle find(final Method method) {
final MethodHandle mh = super.find(method);
return debug(mh, "find", method);
try {
final MethodHandle mh = PUBLIC_LOOKUP.unreflect(method);
return debug(mh, "find", method);
} catch (final IllegalAccessException e) {
throw new LookupException(e);
}
}
@Override
public MethodHandle findStatic(final MethodHandles.Lookup explicitLookup, final Class<?> clazz, final String name, final MethodType type) {
final MethodHandle mh = super.findStatic(explicitLookup, clazz, name, type);
return debug(mh, "findStatic", explicitLookup, clazz, name, type);
try {
final MethodHandle mh = explicitLookup.findStatic(clazz, name, type);
return debug(mh, "findStatic", explicitLookup, clazz, name, type);
} catch (final NoSuchMethodException | IllegalAccessException e) {
throw new LookupException(e);
}
}
@Override
public MethodHandle findSpecial(final MethodHandles.Lookup explicitLookup, final Class<?> clazz, final String name, final MethodType type, final Class<?> thisClass) {
try {
final MethodHandle mh = explicitLookup.findSpecial(clazz, name, type, thisClass);
return debug(mh, "findSpecial", explicitLookup, clazz, name, type);
} catch (final NoSuchMethodException | IllegalAccessException e) {
throw new LookupException(e);
}
}
@Override
public MethodHandle findVirtual(final MethodHandles.Lookup explicitLookup, final Class<?> clazz, final String name, final MethodType type) {
final MethodHandle mh = super.findVirtual(explicitLookup, clazz, name, type);
return debug(mh, "findVirtual", explicitLookup, clazz, name, type);
try {
final MethodHandle mh = explicitLookup.findVirtual(clazz, name, type);
return debug(mh, "findVirtual", explicitLookup, clazz, name, type);
} catch (final NoSuchMethodException | IllegalAccessException e) {
throw new LookupException(e);
}
}
@Override
public SwitchPoint createSwitchPoint() {
final SwitchPoint sp = super.createSwitchPoint();
LOG.log(TRACE_LEVEL, "createSwitchPoint ", sp);
final SwitchPoint sp = new SwitchPoint();
log.log(TRACE_LEVEL, "createSwitchPoint ", sp);
return sp;
}
@Override
public MethodHandle guardWithTest(final SwitchPoint sp, final MethodHandle before, final MethodHandle after) {
final MethodHandle mh = super.guardWithTest(sp, before, after);
final MethodHandle mh = sp.guardWithTest(before, after);
return debug(mh, "guardWithTest", sp, before, after);
}
@Override
public MethodType type(final Class<?> returnType, final Class<?>... paramTypes) {
final MethodType mt = super.type(returnType, paramTypes);
LOG.log(TRACE_LEVEL, "methodType ", returnType, " ", Arrays.toString(paramTypes), " ", mt);
final MethodType mt = MethodType.methodType(returnType, paramTypes);
log.log(TRACE_LEVEL, "methodType ", returnType, " ", Arrays.toString(paramTypes), " ", mt);
return mt;
}
}
/**
* Class used for debugging Nashorn generated method handles
*/
private static class TraceCreateMethodHandleFunctionality extends TraceMethodHandleFunctionality {
@Override
public MethodHandle debug(final MethodHandle master, final String str, final Object... args) {
LOG.log(TRACE_LEVEL, str, " ", describe(args));
stacktrace(LOG);
return master;
}
}
}

View File

@ -337,5 +337,6 @@ public interface MethodHandleFunctionality {
* @return the method type
*/
public MethodType type(Class<?> returnType, Class<?>... paramTypes);
}

View File

@ -44,12 +44,15 @@ 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 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;
@ -70,7 +73,11 @@ 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;
/**
@ -430,6 +437,13 @@ 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);
}
@Override
protected Context getContext() {
return context;
@ -465,7 +479,8 @@ public final class Global extends ScriptObject implements Scope {
this.context = context;
this.setIsScope();
this.optimisticFunctionMap = new HashMap<>();
GlobalConstants.instance().invalidateAll();
final GlobalConstants gc = GlobalConstants.instance(this);
gc.invalidateAll();
}
/**
@ -479,6 +494,14 @@ public final class Global extends ScriptObject implements Scope {
return global;
}
/**
* Check if we have a Global instance
* @return true if one exists
*/
public static boolean hasInstance() {
return Context.getGlobal() != null;
}
/**
* Script access to {@link ScriptEnvironment}
*
@ -1691,6 +1714,8 @@ public final class Global extends ScriptObject implements Scope {
// synonym for "arguments" in scripting mode
addOwnProperty("$ARG", argumentsFlags, argumentsObject);
}
initLoggers();
}
private void initErrorObjects() {
@ -2072,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) {
ApplySpecialization.getLogger().info("Overwrote special name '" + name +"' - invalidating switchpoint");
getLogger(ApplySpecialization.class).info("Overwrote special name '" + name +"' - invalidating switchpoint");
SwitchPoint.invalidateAll(new SwitchPoint[] { sp });
}
}
@ -2088,4 +2113,73 @@ public final class Global extends ScriptObject implements Scope {
final MethodHandle target = MH.insertArguments(Global.instance().INVALIDATE_RESERVED_NAME, 0, name);
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

@ -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.runtime.DebugLogger;
import jdk.nashorn.internal.objects.Global;
import jdk.nashorn.internal.runtime.ErrorManager;
import jdk.nashorn.internal.runtime.JSErrorType;
import jdk.nashorn.internal.runtime.ParserException;
@ -114,11 +114,15 @@ import jdk.nashorn.internal.runtime.ScriptEnvironment;
import jdk.nashorn.internal.runtime.ScriptingFunctions;
import jdk.nashorn.internal.runtime.Source;
import jdk.nashorn.internal.runtime.Timing;
import jdk.nashorn.internal.runtime.logging.DebugLogger;
import jdk.nashorn.internal.runtime.logging.Loggable;
import jdk.nashorn.internal.runtime.logging.Logger;
/**
* Builds the IR.
*/
public class Parser extends AbstractParser {
@Logger(name="parser")
public class Parser extends AbstractParser implements Loggable {
private static final String ARGUMENTS_NAME = CompilerConstants.ARGUMENTS_VAR.symbolName();
/** Current script environment. */
@ -135,7 +139,7 @@ public class Parser extends AbstractParser {
/** Namespace for function names where not explicitly given */
private final Namespace namespace;
private static final DebugLogger LOG = new DebugLogger("parser");
private final DebugLogger log;
/** to receive line information from Lexer when scanning multine literals. */
protected final Lexer.LineInfoReceiver lineInfoReceiver;
@ -194,6 +198,18 @@ public class Parser extends AbstractParser {
// non-scripting mode script can't have multi-line literals
this.lineInfoReceiver = null;
}
this.log = !Global.hasInstance() ? DebugLogger.DISABLED_LOGGER : initLogger(Global.instance());
}
@Override
public DebugLogger getLogger() {
return log;
}
@Override
public DebugLogger initLogger(final Global global) {
return global.getLogger(this.getClass());
}
/**
@ -250,7 +266,7 @@ public class Parser extends AbstractParser {
*/
public FunctionNode parse(final String scriptName, final int startPos, final int len, final boolean allowPropertyFunction) {
final long t0 = Timing.isEnabled() ? System.currentTimeMillis() : 0L;
LOG.info(this, " begin for '", scriptName, "'");
log.info(this, " begin for '", scriptName, "'");
try {
stream = new TokenStream();
@ -271,9 +287,9 @@ public class Parser extends AbstractParser {
final String end = this + " end '" + scriptName + "'";
if (Timing.isEnabled()) {
Timing.accumulateTime(toString(), System.currentTimeMillis() - t0);
LOG.info(end, "' in ", System.currentTimeMillis() - t0, " ms");
log.info(end, "' in ", System.currentTimeMillis() - t0, " ms");
} else {
LOG.info(end);
log.info(end);
}
}
}
@ -2538,7 +2554,7 @@ loop:
return nodeList;
}
private static <T> List<T> optimizeList(ArrayList<T> list) {
private static <T> List<T> optimizeList(final ArrayList<T> list) {
switch(list.size()) {
case 0: {
return Collections.emptyList();
@ -2668,7 +2684,7 @@ loop:
return isValidIdentifier(defaultFunctionName) ? defaultFunctionName : ANON_FUNCTION_PREFIX.symbolName() + functionLine;
}
private static boolean isValidIdentifier(String name) {
private static boolean isValidIdentifier(final String name) {
if(name == null || name.isEmpty()) {
return false;
}

View File

@ -25,14 +25,12 @@
package jdk.nashorn.internal.runtime;
import static jdk.nashorn.internal.codegen.ObjectClassGenerator.DEBUG_FIELDS;
import static jdk.nashorn.internal.codegen.ObjectClassGenerator.OBJECT_FIELDS_ONLY;
import static jdk.nashorn.internal.codegen.ObjectClassGenerator.PRIMITIVE_FIELD_TYPE;
import static jdk.nashorn.internal.codegen.ObjectClassGenerator.createGetter;
import static jdk.nashorn.internal.codegen.ObjectClassGenerator.createSetter;
import static jdk.nashorn.internal.codegen.ObjectClassGenerator.getFieldCount;
import static jdk.nashorn.internal.codegen.ObjectClassGenerator.getFieldName;
import static jdk.nashorn.internal.codegen.ObjectClassGenerator.shouldInstrument;
import static jdk.nashorn.internal.lookup.Lookup.MH;
import static jdk.nashorn.internal.lookup.MethodHandleFactory.stripName;
import static jdk.nashorn.internal.runtime.JSType.getAccessorTypeIndex;
@ -42,12 +40,12 @@ import static jdk.nashorn.internal.runtime.UnwarrantedOptimismException.INVALID_
import java.lang.invoke.MethodHandle;
import java.lang.invoke.MethodHandles;
import java.lang.invoke.SwitchPoint;
import java.util.function.Supplier;
import java.util.logging.Level;
import jdk.nashorn.internal.codegen.ObjectClassGenerator;
import jdk.nashorn.internal.codegen.types.Type;
import jdk.nashorn.internal.lookup.Lookup;
import jdk.nashorn.internal.lookup.MethodHandleFactory;
import jdk.nashorn.internal.objects.Global;
/**
@ -56,14 +54,14 @@ import jdk.nashorn.internal.objects.Global;
*/
public class AccessorProperty extends Property {
private static final MethodHandles.Lookup LOOKUP = MethodHandles.lookup();
private static final MethodHandle REPLACE_MAP = findOwnMH("replaceMap", Object.class, Object.class, PropertyMap.class, String.class, Class.class, Class.class);
private static final MethodHandle REPLACE_MAP = findOwnMH_S("replaceMap", Object.class, Object.class, PropertyMap.class);
private static final MethodHandle INVALIDATE_SP = findOwnMH_S("invalidateSwitchPoint", Object.class, Object.class, SwitchPoint.class);
private static final SwitchPoint NO_CHANGE_CALLBACK = new SwitchPoint();
private static final int NOOF_TYPES = getNumberOfAccessorTypes();
private static final DebugLogger LOG = ObjectClassGenerator.getLogger();
private static final MethodHandle INVALIDATE_SP = findOwnMH("invalidateSwitchPoint", Object.class, Object.class, SwitchPoint.class, String.class);
/**
* Properties in different maps for the same structure class will share their field getters and setters. This could
* be further extended to other method handles that are looked up in the AccessorProperty constructor, but right now
@ -376,9 +374,6 @@ public class AccessorProperty extends Property {
if (!canBeUndefined()) { //todo if !canBeUndefined it means that we have an exact initialType
initialType = int.class;
}
if (shouldInstrument(getKey())) {
info(getKey(), canBeUndefined() ? " can be undefined" : " is always defined");
}
}
setCurrentType(initialType);
}
@ -594,27 +589,19 @@ public class AccessorProperty extends Property {
// the final three arguments are for debug printout purposes only
@SuppressWarnings("unused")
private static Object replaceMap(final Object sobj, final PropertyMap newMap, final String key, final Class<?> oldType, final Class<?> newType) {
if (DEBUG_FIELDS && shouldInstrument(key)) {
final PropertyMap oldMap = ((ScriptObject)sobj).getMap();
info("Type change for '" + key + "' " + oldType + "=>" + newType);
finest("setting map " + key+ " => " + sobj + " from " + Debug.id(oldMap) + " to " + Debug.id(newMap) + " " + oldMap + " => " + newMap);
}
private static Object replaceMap(final Object sobj, final PropertyMap newMap) {
((ScriptObject)sobj).setMap(newMap);
return sobj;
}
@SuppressWarnings("unused")
private static Object invalidateSwitchPoint(final Object obj, final SwitchPoint sp, final String key) {
LOG.info("Field change callback for " + key + " triggered: " + sp);
private static Object invalidateSwitchPoint(final Object obj, final SwitchPoint sp) {
SwitchPoint.invalidateAll(new SwitchPoint[] { sp });
return obj;
}
private MethodHandle generateSetter(final Class<?> forType, final Class<?> type) {
MethodHandle mh = createSetter(forType, type, primitiveSetter, objectSetter);
mh = debug(mh, getCurrentType(), type, "set");
return mh;
return debug(createSetter(forType, type, primitiveSetter, objectSetter), getCurrentType(), type, "set");
}
/**
@ -638,8 +625,8 @@ public class AccessorProperty extends Property {
final PropertyMap newMap = getWiderMap(currentMap, newProperty);
final MethodHandle widerSetter = newProperty.getSetter(type, newMap);
final Class<?> ct = getCurrentType();
mh = MH.filterArguments(widerSetter, 0, MH.insertArguments(REPLACE_MAP, 1, newMap, getKey(), ct, type));
final Class<?> ct = getCurrentType();
mh = MH.filterArguments(widerSetter, 0, MH.insertArguments(debugReplace(ct, type, currentMap, newMap) , 1, newMap));
if (ct != null && ct.isPrimitive() && !type.isPrimitive()) {
mh = ObjectClassGenerator.createGuardBoxedPrimitiveSetter(ct, generateSetter(ct, ct), mh);
}
@ -652,16 +639,14 @@ public class AccessorProperty extends Property {
*/
final SwitchPoint ccb = getChangeCallback();
if (ccb != null && ccb != NO_CHANGE_CALLBACK) {
mh = MH.filterArguments(mh, 0, MH.insertArguments(INVALIDATE_SP, 1, changeCallback, getKey()));
mh = MH.filterArguments(mh, 0, MH.insertArguments(debugInvalidate(getKey(), ccb), 1, changeCallback));
}
assert mh.type().returnType() == void.class;
assert mh.type().returnType() == void.class : mh.type();
return mh;
}
private static final SwitchPoint NO_CHANGE_CALLBACK = new SwitchPoint();
/**
* Get the change callback for this property
* @return switchpoint that is invalidated when property changes
@ -693,32 +678,6 @@ public class AccessorProperty extends Property {
return canChangeType() && ti > fti;
}
// for loggers below, don't bother generating potentially expensive string concat
// operations that will be thrown away anyway, if the level isn't finer than ior
// equal to info
private static void finest(final String... strs) {
if (DEBUG_FIELDS && LOG.levelFinerThanOrEqual(Level.INFO)) {
LOG.finest((Object[])strs);
}
}
private static void info(final String... strs) {
if (DEBUG_FIELDS && LOG.levelFinerThanOrEqual(Level.INFO)) {
LOG.info((Object[])strs);
}
}
private MethodHandle debug(final MethodHandle mh, final Class<?> forType, final Class<?> type, final String tag) {
if (DEBUG_FIELDS && LOG.levelFinerThanOrEqual(Level.INFO) && shouldInstrument(getKey())) {
return MethodHandleFactory.addDebugPrintout(
LOG,
Level.INFO,
mh,
tag + " '" + getKey() + "' (property="+ Debug.id(this) + ", slot=" + getSlot() + " " + getClass().getSimpleName() + " forType=" + stripName(forType) + ", type=" + stripName(type) + ')');
}
return mh;
}
@Override
public final void setCurrentType(final Class<?> currentType) {
assert currentType != boolean.class : "no boolean storage support yet - fix this";
@ -730,8 +689,74 @@ public class AccessorProperty extends Property {
return currentType;
}
private static MethodHandle findOwnMH(final String name, final Class<?> rtype, final Class<?>... types) {
return MH.findStatic(LOOKUP, AccessorProperty.class, name, MH.type(rtype, types));
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) + ')';
}
});
}
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;
}
return REPLACE_MAP;
}
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;
}
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,8 +41,10 @@ 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;
/**
* An version of a JavaScript function, native or JavaScript.
@ -55,7 +57,7 @@ final class CompiledFunction {
private static final MethodHandle HANDLE_REWRITE_EXCEPTION = findOwnMH("handleRewriteException", MethodHandle.class, CompiledFunction.class, OptimismInfo.class, RewriteException.class);
private static final MethodHandle RESTOF_INVOKER = MethodHandles.exactInvoker(MethodType.methodType(Object.class, RewriteException.class));
private static final DebugLogger LOG = RecompilableScriptFunctionData.getLogger();
private final DebugLogger log;
/**
* The method type may be more specific than the invoker, if. e.g.
@ -71,6 +73,7 @@ final class CompiledFunction {
CompiledFunction(final MethodHandle invoker) {
this.invoker = invoker;
this.log = Global.instance().getLogger(RecompilableScriptFunctionData.class);
}
static CompiledFunction createBuiltInConstructor(final MethodHandle invoker) {
@ -576,8 +579,8 @@ final class CompiledFunction {
final MethodType callSiteType = type.parameterType(0) == ScriptFunction.class ? type : type.insertParameterTypes(0, ScriptFunction.class);
final FunctionNode fn = oldOptimismInfo.recompile(callSiteType, re);
if (LOG.isEnabled()) {
LOG.info(new RecompilationEvent(Level.INFO, re, re.getReturnValueNonDestructive()), "\tRewriteException ", re.getMessageShort());
if (log.isEnabled()) {
log.info(new RecompilationEvent(Level.INFO, re, re.getReturnValueNonDestructive()), "\tRewriteException ", re.getMessageShort());
}
// It didn't necessarily recompile, e.g. for an outer invocation of a recursive function if we already
@ -588,8 +591,8 @@ final class CompiledFunction {
//is recompiled
assert optimismInfo == oldOptimismInfo;
isOptimistic = fn.isOptimistic();
if (LOG.isEnabled()) {
LOG.info("Recompiled '", fn.getName(), "' (", Debug.id(this), ")", isOptimistic ? " remains optimistic." : " is no longer optimistic.");
if (log.isEnabled()) {
log.info("Recompiled '", fn.getName(), "' (", Debug.id(this), ")", isOptimistic ? " remains optimistic." : " is no longer optimistic.");
}
final MethodHandle newInvoker = oldOptimismInfo.data.lookup(fn);
invoker = newInvoker.asType(type.changeReturnType(newInvoker.type().returnType()));
@ -617,6 +620,7 @@ 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);
OptimismInfo(final RecompilableScriptFunctionData data) {
this.data = data;
@ -633,7 +637,7 @@ final class CompiledFunction {
if (previousFailedType != null && !previousFailedType.narrowerThan(retType)) {
final StackTraceElement[] stack = e.getStackTrace();
final String functionId = stack.length == 0 ? data.getName() : stack[0].getClassName() + "." + stack[0].getMethodName();
LOG.info("RewriteException for an already invalidated program point ", e.getProgramPoint(), " in ", functionId, ". This is okay for a recursive function invocation, but a bug otherwise.");
log.info("RewriteException for an already invalidated program point ", e.getProgramPoint(), " in ", functionId, ". This is okay for a recursive function invocation, but a bug otherwise.");
return null;
}
SwitchPoint.invalidateAll(new SwitchPoint[] { optimisticAssumptions });

View File

@ -65,6 +65,7 @@ import jdk.nashorn.internal.ir.debug.PrintVisitor;
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.options.Options;
/**
@ -195,7 +196,7 @@ 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().invalidateAll();
GlobalConstants.instance(global).invalidateAll();
currentGlobal.set(global);
}
@ -915,9 +916,9 @@ public final class Context {
Class<?> script = findCachedClass(source);
if (script != null) {
final DebugLogger LOG = Compiler.getLogger();
if (LOG.isEnabled()) {
LOG.fine(new RuntimeEvent<>(Level.INFO, source), "Code cache hit for ", source, " avoiding recompile.");
final DebugLogger log = Global.instance().getLogger(Compiler.class);
if (log.isEnabled()) {
log.fine(new RuntimeEvent<>(Level.INFO, source), "Code cache hit for ", source, " avoiding recompile.");
}
return script;
}

View File

@ -26,7 +26,8 @@
package jdk.nashorn.internal.runtime;
import static jdk.nashorn.internal.codegen.CompilerConstants.staticCall;
import static jdk.nashorn.internal.runtime.DebugLogger.quote;
import static jdk.nashorn.internal.codegen.CompilerConstants.virtualCall;
import static jdk.nashorn.internal.runtime.logging.DebugLogger.quote;
import static jdk.nashorn.internal.lookup.Lookup.MH;
import java.lang.invoke.MethodHandle;
@ -43,7 +44,11 @@ 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;
import jdk.nashorn.internal.runtime.logging.Logger;
/**
* Each global owns one of these. This is basically table of accessors
@ -67,21 +72,10 @@ import jdk.nashorn.internal.runtime.linker.NashornCallSiteDescriptor;
* a receiver guard on the constant getter, but it currently leaks memory and its benefits
* have not yet been investigated property.
*/
public final class GlobalConstants {
private GlobalConstants() {
//singleton
}
/**
* Return the singleton global constant pool
* @return singleton global constant pool
*/
public static GlobalConstants instance() {
return instance;
}
private static final GlobalConstants instance = new GlobalConstants();
@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.
@ -92,11 +86,11 @@ public final class GlobalConstants {
private static final MethodHandles.Lookup LOOKUP = MethodHandles.lookup();
private static final MethodHandle INVALIDATE_SP = staticCall(LOOKUP, GlobalConstants.class, "invalidateSwitchPoint", Object.class, Object.class, Access.class).methodHandle();
private static final MethodHandle INVALIDATE_SP = virtualCall(LOOKUP, GlobalConstants.class, "invalidateSwitchPoint", Object.class, Object.class, Access.class).methodHandle();
private static final MethodHandle RECEIVER_GUARD = staticCall(LOOKUP, GlobalConstants.class, "receiverGuard", boolean.class, Access.class, Object.class, Object.class).methodHandle();
/** Logger for constant getters */
private static final DebugLogger LOG = new DebugLogger("const");
private final DebugLogger log;
/**
* Access map for this global - associates a symbol name with an Access object, with getter
@ -104,6 +98,32 @@ public final class GlobalConstants {
*/
private final Map<String, Access> map = new HashMap<>();
private GlobalConstants(final Global global) {
this.log = initLogger(global);
}
@Override
public DebugLogger getLogger() {
return log;
}
@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;
}
/**
* Information about a constant access and its potential invalidations
*/
@ -205,7 +225,7 @@ public final class GlobalConstants {
* will have changed.
*/
public void invalidateAll() {
LOG.info("New global created - invalidating all constant callsites without increasing invocation count.");
log.info("New global created - invalidating all constant callsites without increasing invocation count.");
for (final Access acc : map.values()) {
acc.invalidateUncounted();
}
@ -221,19 +241,19 @@ public final class GlobalConstants {
* @return receiver, so this can be used as param filter
*/
@SuppressWarnings("unused")
private static Object invalidateSwitchPoint(final Object obj, final Access acc) {
if (LOG.isEnabled()) {
LOG.info("*** Invalidating switchpoint " + acc.getSwitchPoint() + " for receiver=" + obj + " access=" + acc);
private Object invalidateSwitchPoint(final Object obj, final Access acc) {
if (log.isEnabled()) {
log.info("*** Invalidating switchpoint " + acc.getSwitchPoint() + " for receiver=" + obj + " access=" + acc);
}
acc.invalidateOnce();
if (acc.mayRetry()) {
if (LOG.isEnabled()) {
LOG.info("Retry is allowed for " + acc + "... Creating a new switchpoint.");
if (log.isEnabled()) {
log.info("Retry is allowed for " + acc + "... Creating a new switchpoint.");
}
acc.newSwitchPoint();
} else {
if (LOG.isEnabled()) {
LOG.info("This was the last time I allowed " + quote(acc.getName()) + " to relink as constant.");
if (log.isEnabled()) {
log.info("This was the last time I allowed " + quote(acc.getName()) + " to relink as constant.");
}
}
return obj;
@ -310,32 +330,33 @@ public final class GlobalConstants {
final Access acc = getOrCreateSwitchPoint(name);
if (LOG.isEnabled()) {
LOG.fine("Trying to link constant SETTER ", acc);
if (log.isEnabled()) {
log.fine("Trying to link constant SETTER ", acc);
}
if (!acc.mayRetry()) {
LOG.info("*** SET: Giving up on " + quote(name) + " - retry count has exceeded " + DynamicLinker.getLinkedCallSiteLocation());
log.info("*** SET: Giving up on " + quote(name) + " - retry count has exceeded " + DynamicLinker.getLinkedCallSiteLocation());
return null;
}
assert acc.mayRetry();
if (acc.hasBeenInvalidated()) {
LOG.info("New chance for " + acc);
log.info("New chance for " + acc);
acc.newSwitchPoint();
}
assert !acc.hasBeenInvalidated();
// if we haven't given up on this symbol, add a switchpoint invalidation filter to the receiver parameter
final MethodHandle target = inv.getInvocation();
final Class<?> receiverType = target.type().parameterType(0);
final MethodHandle invalidator = MH.asType(INVALIDATE_SP, INVALIDATE_SP.type().changeParameterType(0, receiverType).changeReturnType(receiverType));
final MethodHandle mh = MH.filterArguments(inv.getInvocation(), 0, MH.insertArguments(invalidator, 1, acc));
final MethodHandle target = inv.getInvocation();
final Class<?> receiverType = target.type().parameterType(0);
final MethodHandle boundInvalidator = MH.bindTo(INVALIDATE_SP, this);
final MethodHandle invalidator = MH.asType(boundInvalidator, boundInvalidator.type().changeParameterType(0, receiverType).changeReturnType(receiverType));
final MethodHandle mh = MH.filterArguments(inv.getInvocation(), 0, MH.insertArguments(invalidator, 1, acc));
assert inv.getSwitchPoints() == null : Arrays.asList(inv.getSwitchPoints());
LOG.info("Linked setter " + quote(name) + " " + acc.getSwitchPoint());
log.info("Linked setter " + quote(name) + " " + acc.getSwitchPoint());
return new GuardedInvocation(mh, inv.getGuard(), acc.getSwitchPoint(), inv.getException());
}
@ -373,15 +394,15 @@ public final class GlobalConstants {
final Access acc = getOrCreateSwitchPoint(name);
LOG.fine("Starting to look up object value " + name);
log.fine("Starting to look up object value " + name);
final Object c = find.getObjectValue();
if (LOG.isEnabled()) {
LOG.fine("Trying to link constant GETTER " + acc + " value = " + c);
if (log.isEnabled()) {
log.fine("Trying to link constant GETTER " + acc + " value = " + c);
}
if (acc.hasBeenInvalidated() || acc.guardFailed()) {
LOG.fine("*** GET: Giving up on " + quote(name) + " - retry count has exceeded");
log.fine("*** GET: Giving up on " + quote(name) + " - retry count has exceeded");
return null;
}
@ -409,9 +430,9 @@ public final class GlobalConstants {
guard = MH.insertArguments(RECEIVER_GUARD, 0, acc, receiver);
}
if (LOG.isEnabled()) {
LOG.info("Linked getter " + quote(name) + " as MethodHandle.constant() -> " + c + " " + acc.getSwitchPoint());
mh = MethodHandleFactory.addDebugPrintout(LOG, Level.FINE, mh, "get const " + acc);
if (log.isEnabled()) {
log.info("Linked getter " + quote(name) + " as MethodHandle.constant() -> " + c + " " + acc.getSwitchPoint());
mh = MethodHandleFactory.addDebugPrintout(log, Level.FINE, mh, "get const " + acc);
}
return new GuardedInvocation(mh, guard, acc.getSwitchPoint(), null);

View File

@ -1,194 +0,0 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package jdk.nashorn.internal.runtime;
import java.security.AccessControlContext;
import java.security.AccessController;
import java.security.Permissions;
import java.security.PrivilegedAction;
import java.security.ProtectionDomain;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Locale;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import java.util.logging.ConsoleHandler;
import java.util.logging.Formatter;
import java.util.logging.Handler;
import java.util.logging.Level;
import java.util.logging.LogRecord;
import java.util.logging.Logger;
import java.util.logging.LoggingPermission;
/**
* Logging system for getting loggers for arbitrary subsystems as
* specified on the command line. Supports all standard log levels
*
*/
public final class Logging {
private Logging() {
}
/** Loggers */
private static final Logger disabledLogger = Logger.getLogger("disabled");
private static AccessControlContext createLoggerControlAccCtxt() {
final Permissions perms = new Permissions();
perms.add(new LoggingPermission("control", null));
return new AccessControlContext(new ProtectionDomain[] { new ProtectionDomain(null, perms) });
}
static {
AccessController.doPrivileged(new PrivilegedAction<Void>() {
@Override
public Void run() {
Logging.disabledLogger.setLevel(Level.OFF);
return null;
}
}, createLoggerControlAccCtxt());
}
/** Maps logger name to loggers. Names are typically per package */
private static final Map<String, Logger> loggers = new HashMap<>();
private static final Set<String> quietLoggers = new HashSet<>();
private static String lastPart(final String packageName) {
final String[] parts = packageName.split("\\.");
if (parts.length == 0) {
return packageName;
}
return parts[parts.length - 1];
}
/**
* Get a logger for a given class, generating a logger name based on the
* class name
*
* @param name the name to use as key for the logger
* @return the logger
*/
public static Logger getLogger(final String name) {
final Logger logger = Logging.loggers.get(name);
if (logger != null) {
return logger;
}
return Logging.disabledLogger;
}
/**
* Get a logger for a given name or create it if not already there, typically
* used for mapping system properties to loggers
*
* @param name the name to use as key
* @param level log lever to reset existing logger with, or create new logger with
* @return the logger
*/
public static Logger getOrCreateLogger(final String name, final Level level) {
final Logger logger = Logging.loggers.get(name);
if (logger == null) {
return instantiateLogger(name, level);
}
logger.setLevel(level);
return logger;
}
/**
* Is this logger "quiet", i.e. does it put events in the debug event
* queue, but refrains from printing anything?
* @param name logger name
* @return true if quiet
*/
public static boolean loggerIsQuiet(final String name) {
return quietLoggers.contains(name);
}
/**
* Initialization function that is called to instantiate the logging system. It takes
* logger names (keys) and logging labels respectively
*
* @param map a map where the key is a logger name and the value a logging level
* @throws IllegalArgumentException if level or names cannot be parsed
*/
public static void initialize(final Map<String, String> map) throws IllegalArgumentException {
try {
for (final Entry<String, String> entry : map.entrySet()) {
Level level;
final String key = entry.getKey();
final String value = entry.getValue();
final String name = Logging.lastPart(key);
if ("".equals(value)) {
level = Level.INFO;
} else if ("quiet".equals(value)) {
level = Level.INFO;
quietLoggers.add(name);
} else {
level = Level.parse(value.toUpperCase(Locale.ENGLISH));
}
final Logger logger = instantiateLogger(name, level);
Logging.loggers.put(name, logger);
}
} catch (final IllegalArgumentException | SecurityException e) {
throw e;
}
}
private static Logger instantiateLogger(final String name, final Level level) {
final Logger logger = java.util.logging.Logger.getLogger(name);
for (final Handler h : logger.getHandlers()) {
logger.removeHandler(h);
}
logger.setLevel(level);
logger.setUseParentHandlers(false);
final Handler c = new ConsoleHandler();
c.setFormatter(new Formatter() {
@Override
public String format(final LogRecord record) {
final StringBuilder sb = new StringBuilder();
sb.append('[')
.append(record.getLoggerName())
.append("] ")
.append(record.getMessage())
.append('\n');
return sb.toString();
}
});
logger.addHandler(c);
c.setLevel(level);
return logger;
}
}

View File

@ -172,7 +172,6 @@ public final class PropertyHashMap implements Map <String, Property> {
*/
public PropertyHashMap immutableReplace(final Property property, final Property newProperty) {
assert property.getKey().equals(newProperty.getKey()) : "replacing properties with different keys: '" + property.getKey() + "' != '" + newProperty.getKey() + "'";
assert property.hashCode() != newProperty.hashCode() : "replacing identical properties: '" + property + "'";
assert findElement(property.getKey()) != null : "replacing property that doesn't exist in map: '" + property.getKey() + "'";
return cloneMap().replaceNoClone(property.getKey(), newProperty);
}

View File

@ -50,9 +50,13 @@ 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;
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;
/**
@ -61,7 +65,8 @@ import jdk.nashorn.internal.runtime.options.Options;
* The common denominator is that it can get new invokers during its lifespan,
* unlike {@code FinalScriptFunctionData}
*/
public final class RecompilableScriptFunctionData extends ScriptFunctionData {
@Logger(name="recompile")
public final class RecompilableScriptFunctionData extends ScriptFunctionData implements Loggable {
/** Is lazy compilation enabled? TODO: this should be the default */
public static final boolean LAZY_COMPILATION = Options.getBooleanProperty("nashorn.lazy");
@ -112,15 +117,7 @@ public final class RecompilableScriptFunctionData extends ScriptFunctionData {
/** Unique id for classes needed to wrap recompiled script functions */
private static final AtomicInteger RECOMPILE_ID = new AtomicInteger(0);
private static final DebugLogger LOG = new DebugLogger("recompile");
/**
* Get the recompilation logger
* @return the logger
*/
public static DebugLogger getLogger() {
return LOG;
}
private final DebugLogger log;
private final Map<String, Integer> externalScopeDepths;
@ -174,6 +171,18 @@ public final class RecompilableScriptFunctionData extends ScriptFunctionData {
assert nfn.getParent() == null;
nfn.setParent(this);
}
this.log = initLogger(Global.instance());
}
@Override
public DebugLogger getLogger() {
return log;
}
@Override
public DebugLogger initLogger(final Global global) {
return global.getLogger(this.getClass());
}
/**
@ -400,8 +409,8 @@ public final class RecompilableScriptFunctionData extends ScriptFunctionData {
}
MethodHandle compileRestOfMethod(final MethodType fnCallSiteType, final Map<Integer, Type> invalidatedProgramPoints, final int[] continuationEntryPoints, final ScriptObject runtimeScope, final FunctionNodeTransform tr) {
if (LOG.isEnabled()) {
LOG.info("Rest-of compilation of '", functionName, "' signature: ", fnCallSiteType, " ", stringifyInvalidations(invalidatedProgramPoints));
if (log.isEnabled()) {
log.info("Rest-of compilation of '", functionName, "' signature: ", fnCallSiteType, " ", stringifyInvalidations(invalidatedProgramPoints));
}
final String scriptName = RECOMPILATION_PREFIX + RECOMPILE_ID.incrementAndGet() + "$restOf";
@ -434,8 +443,8 @@ public final class RecompilableScriptFunctionData extends ScriptFunctionData {
final String scriptName = RECOMPILATION_PREFIX + RECOMPILE_ID.incrementAndGet();
final MethodType fnCallSiteType = actualCallSiteType == null ? null : actualCallSiteType.changeParameterType(0, ScriptFunction.class);
if (LOG.isEnabled()) {
LOG.info(reason, " of '", functionName, "' signature: ", fnCallSiteType, " ", stringifyInvalidations(invalidatedProgramPoints));
if (log.isEnabled()) {
log.info(reason, " of '", functionName, "' signature: ", fnCallSiteType, " ", stringifyInvalidations(invalidatedProgramPoints));
}
FunctionNode fn = tr.apply(reparse(scriptName));

View File

@ -26,15 +26,20 @@
package jdk.nashorn.internal.runtime;
import java.io.PrintWriter;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Set;
import java.util.StringTokenizer;
import java.util.TimeZone;
import jdk.nashorn.internal.codegen.Namespace;
import jdk.nashorn.internal.runtime.linker.NashornCallSiteDescriptor;
import jdk.nashorn.internal.runtime.options.KeyValueOption;
import jdk.nashorn.internal.runtime.options.LoggingOption;
import jdk.nashorn.internal.runtime.options.LoggingOption.LoggerInfo;
import jdk.nashorn.internal.runtime.options.Option;
import jdk.nashorn.internal.runtime.options.Options;
@ -197,6 +202,9 @@ public final class ScriptEnvironment {
/** Local for error messages */
public final Locale _locale;
/** Logging */
public final Map<String, LoggerInfo> _loggers;
/**
* Constructor
*
@ -310,6 +318,9 @@ public final class ScriptEnvironment {
} else {
this._locale = Locale.getDefault();
}
final LoggingOption lo = (LoggingOption)options.get("log");
this._loggers = lo == null ? new HashMap<String, LoggerInfo>() : lo.getLoggers();
}
/**
@ -367,4 +378,15 @@ public final class ScriptEnvironment {
return options.getArguments();
}
/**
* Check if there is a logger registered for a particular name: typically
* the "name" attribute of a Loggable annotation on a class
*
* @param name logger name
* @return true, if a logger exists for that name, false otherwise
*/
public boolean hasLogger(final String name) {
return _loggers.get(name) != null;
}
}

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
ApplySpecialization.getLogger().info("Collection arguments to revert call to apply in " + appliedFn);
Global.instance().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().delete(property.getKey());
GlobalConstants.instance(Global.instance()).delete(property.getKey());
return true;
}
}
@ -1930,7 +1930,7 @@ public abstract class ScriptObject implements PropertyAccess {
}
}
final GuardedInvocation cinv = GlobalConstants.instance().findGetMethod(find, this, desc, request, operator);
final GuardedInvocation cinv = GlobalConstants.instance(Global.instance()).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) {
ObjectClassGenerator.getLogger().warning("Megamorphic getter: " + desc + " " + name + " " +isMethod);
Global.instance().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().findSetMethod(find, this, inv, desc, request);
final GuardedInvocation cinv = GlobalConstants.instance(Global.instance()).findSetMethod(find, this, inv, desc, request);
if (cinv != null) {
return cinv;
}

View File

@ -41,18 +41,22 @@ 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.runtime.DebugLogger;
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;
/**
* Interface implemented by all arrays that are directly accessible as underlying
* native arrays
*/
public abstract class ContinuousArrayData extends ArrayData {
@Logger(name="arrays")
public abstract class ContinuousArrayData extends ArrayData implements Loggable {
/** Logger for array accessor linkage */
protected static DebugLogger LOG = new DebugLogger("arrays");
protected final DebugLogger log;
private SwitchPoint sp;
@ -62,6 +66,17 @@ public abstract class ContinuousArrayData extends ArrayData {
*/
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() {
@ -234,8 +249,8 @@ public abstract class ContinuousArrayData extends ArrayData {
}
}
if (LOG.isEnabled()) {
LOG.info(getClass().getSimpleName() + ": Missed fast GETTER " + clazz.getSimpleName() + " " + desc + " " + " line:" + DynamicLinker.getLinkedCallSiteLocation().getLineNumber());
if (log.isEnabled()) {
log.info(getClass().getSimpleName() + ": Missed fast GETTER " + clazz.getSimpleName() + " " + desc + " " + " line:" + DynamicLinker.getLinkedCallSiteLocation().getLineNumber());
}
return null;
@ -275,8 +290,8 @@ public abstract class ContinuousArrayData extends ArrayData {
}
}
if (LOG.isEnabled()) {
LOG.info(getClass().getSimpleName() + ": Missed fast SETTER " + clazz.getSimpleName() + " " + desc + " " + " line:" + DynamicLinker.getLinkedCallSiteLocation().getLineNumber());
if (log.isEnabled()) {
log.info(getClass().getSimpleName() + ": Missed fast SETTER " + clazz.getSimpleName() + " " + desc + " " + " line:" + DynamicLinker.getLinkedCallSiteLocation().getLineNumber());
}
return null;

View File

@ -190,8 +190,8 @@ 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());
if (log.isEnabled()) {
log.info(clazz.getSimpleName() + ": Missed fast GETTER " + clazz.getSimpleName() + " " + desc + " " + " line:" + DynamicLinker.getLinkedCallSiteLocation().getLineNumber());
}
return null;
@ -205,8 +205,8 @@ 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());
if (log.isEnabled()) {
log.info(clazz.getSimpleName() + ": Missed fast SETTER " + clazz.getSimpleName() + " " + desc + " " + " line:" + DynamicLinker.getLinkedCallSiteLocation().getLineNumber());
}
return null;

View File

@ -27,6 +27,7 @@ package jdk.nashorn.internal.runtime.events;
import java.util.logging.Level;
import jdk.nashorn.internal.objects.Global;
import jdk.nashorn.internal.runtime.RecompilableScriptFunctionData;
import jdk.nashorn.internal.runtime.RewriteException;
@ -50,9 +51,10 @@ public final class RecompilationEvent extends RuntimeEvent<RewriteException> {
* {@link RewriteException#getReturnValueNonDestructive()} public, we pass it as
* an extra parameter, rather than querying the getter from another package.
*/
@SuppressWarnings("javadoc")
public RecompilationEvent(final Level level, final RewriteException rewriteException, final Object returnValue) {
super(level, rewriteException);
assert RecompilableScriptFunctionData.getLogger().isEnabled() :
assert Global.instance().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

@ -23,21 +23,38 @@
* questions.
*/
package jdk.nashorn.internal.runtime;
package jdk.nashorn.internal.runtime.logging;
import java.io.PrintWriter;
import java.security.AccessControlContext;
import java.security.AccessController;
import java.security.Permissions;
import java.security.PrivilegedAction;
import java.security.ProtectionDomain;
import java.util.logging.ConsoleHandler;
import java.util.logging.Formatter;
import java.util.logging.Handler;
import java.util.logging.Level;
import java.util.logging.LogRecord;
import java.util.logging.Logger;
import java.util.logging.LoggingPermission;
import jdk.nashorn.internal.objects.Global;
import jdk.nashorn.internal.runtime.Context;
import jdk.nashorn.internal.runtime.ScriptFunction;
import jdk.nashorn.internal.runtime.ScriptObject;
import jdk.nashorn.internal.runtime.ScriptRuntime;
import jdk.nashorn.internal.runtime.events.RuntimeEvent;
import jdk.nashorn.internal.runtime.options.Options;
/**
* Wrapper class for Logging system. This is how you are supposed to register a logger and use it
*/
public final class DebugLogger {
/** Disabled logger used for all loggers that need an instance, but shouldn't output anything */
public static final DebugLogger DISABLED_LOGGER = new DebugLogger("disabled", Level.OFF, false);
private final Logger logger;
private final boolean isEnabled;
@ -48,40 +65,64 @@ public final class DebugLogger {
/** A quiet logger only logs {@link RuntimeEvent}s and does't output any text, regardless of level */
private final boolean isQuiet;
/**
* Constructor
*
* @param loggerName name of logger - this is the unique key with which it can be identified
*/
public DebugLogger(final String loggerName) {
this(loggerName, null);
}
/**
* Constructor
*
* A logger can be paired with a property, e.g. {@code --log:codegen:info} is equivalent to {@code -Dnashorn.codegen.log}
*
* @param loggerName name of logger - this is the unique key with which it can be identified
* @param property system property activating the logger on {@code info} level
* @param loggerName name of logger - this is the unique key with which it can be identified
* @param loggerLevel level of the logger
* @param isQuiet is this a quiet logger, i.e. enabled for things like e.g. RuntimeEvent:s, but quiet otherwise
*/
public DebugLogger(final String loggerName, final String property) {
if (property != null && Options.getBooleanProperty(property)) {
this.logger = Logging.getOrCreateLogger(loggerName, Level.INFO);
} else {
this.logger = Logging.getLogger(loggerName);
}
this.isQuiet = Logging.loggerIsQuiet(loggerName);
public DebugLogger(final String loggerName, final Level loggerLevel, final boolean isQuiet) {
this.logger = instantiateLogger(loggerName, loggerLevel);
this.isQuiet = isQuiet;
assert logger != null;
this.isEnabled = getLevel() != Level.OFF;
}
private static Logger instantiateLogger(final String name, final Level level) {
final Logger logger = java.util.logging.Logger.getLogger(name);
AccessController.doPrivileged(new PrivilegedAction<Void>() {
@Override
public Void run() {
for (final Handler h : logger.getHandlers()) {
logger.removeHandler(h);
}
logger.setLevel(level);
logger.setUseParentHandlers(false);
final Handler c = new ConsoleHandler();
c.setFormatter(new Formatter() {
@Override
public String format(final LogRecord record) {
final StringBuilder sb = new StringBuilder();
sb.append('[')
.append(record.getLoggerName())
.append("] ")
.append(record.getMessage())
.append('\n');
return sb.toString();
}
});
logger.addHandler(c);
c.setLevel(level);
return null;
}
}, createLoggerControlAccCtxt());
return logger;
}
/**
* Do not currently support chaining this with parent logger. Logger level null
* means disabled
* @return level
*/
private Level getLevel() {
public Level getLevel() {
return logger.getLevel() == null ? Level.OFF : logger.getLevel();
}
@ -543,4 +584,15 @@ public final class DebugLogger {
log(level, sb.toString());
}
}
/**
* Access control context for logger level and instantiation permissions
* @return access control context
*/
private static AccessControlContext createLoggerControlAccCtxt() {
final Permissions perms = new Permissions();
perms.add(new LoggingPermission("control", null));
return new AccessControlContext(new ProtectionDomain[] { new ProtectionDomain(null, perms) });
}
}

View File

@ -0,0 +1,56 @@
/*
* Copyright (c) 2010, 2014, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package jdk.nashorn.internal.runtime.logging;
import jdk.nashorn.internal.objects.Global;
/**
* Interface implemented by classes that are loggable.
* Their instances will provide functionality for initializing
* a logger (usually by asking Global for it, with a reference
* to this.getClass()) and a method to return the logger in
* use
*
* Typically a class implementing this interface also has the
* Logger annotation
*
* @see Logger
*/
public interface Loggable {
/**
* Initialize a logger, by asking Global to get or create it
* and then keep it in a table by name
*
* @param global global
* @return the initialized logger
*/
public DebugLogger initLogger(final Global global);
/**
* Return the logger in use
* @return logger
*/
public DebugLogger getLogger();
}

View File

@ -0,0 +1,48 @@
/*
* Copyright (c) 2010, 2014, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package jdk.nashorn.internal.runtime.logging;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
/**
* This annotation is associated with a class that has a logger.
* It contains a name property of the logger name. e.g. a class
* whose logger can be initialized by --log:fields, should be
* annotated @Logger(name="fields"). Multiple classes can have
* the same annotation, which will make them use the same logger
* object. Usually a class with this annotation is also a Loggable,
* but it is not a hard demand
*
* @see Loggable
*/
@Retention(RetentionPolicy.RUNTIME)
public @interface Logger {
/**
* Get the name of the logger
* @return logger name
*/
public String name() default "";
}

View File

@ -36,7 +36,7 @@ import java.util.StringTokenizer;
*
* {@code --log=module1:level1,module2:level2... }
*/
public final class KeyValueOption extends Option<String> {
public class KeyValueOption extends Option<String> {
/**
* Map of keys given
*/

View File

@ -0,0 +1,133 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package jdk.nashorn.internal.runtime.options;
import java.util.Collections;
import java.util.HashMap;
import java.util.Locale;
import java.util.Map;
import java.util.Map.Entry;
import java.util.logging.Level;
/**
* Class that collects logging options like --log=compiler:finest,fields,recompile:fine into
* a map form that can be used to instantiate loggers in the Global object on demand
*/
public class LoggingOption extends KeyValueOption {
/**
* Logging info. Basically a logger name maps to this,
* which is a tuple of log level and the "is quiet" flag,
* which is a special log level used to collect RuntimeEvents
* only, but not output anything
*/
public static class LoggerInfo {
private final Level level;
private final boolean isQuiet;
LoggerInfo(final Level level, final boolean isQuiet) {
this.level = level;
this.isQuiet = isQuiet;
}
/**
* Get the log level
* @return log level
*/
public Level getLevel() {
return level;
}
/**
* Get the quiet flag
* @return true if quiet flag is set
*/
public boolean isQuiet() {
return isQuiet;
}
}
private final Map<String, LoggerInfo> loggers = new HashMap<>();
LoggingOption(final String value) {
super(value);
initialize(getValues());
}
/**
* Return the logger info collected from this command line option
*
* @return map of logger name to logger info
*/
public Map<String, LoggerInfo> getLoggers() {
return Collections.unmodifiableMap(loggers);
}
/**
* Initialization function that is called to instantiate the logging system. It takes
* logger names (keys) and logging labels respectively
*
* @param map a map where the key is a logger name and the value a logging level
* @throws IllegalArgumentException if level or names cannot be parsed
*/
private void initialize(final Map<String, String> logMap) throws IllegalArgumentException {
try {
for (final Entry<String, String> entry : logMap.entrySet()) {
Level level;
final String name = lastPart(entry.getKey());
final String levelString = entry.getValue().toUpperCase(Locale.ENGLISH);
final boolean isQuiet;
if ("".equals(levelString)) {
level = Level.INFO;
isQuiet = false;
} else if ("QUIET".equals(levelString)) {
level = Level.INFO;
isQuiet = true;
} else {
level = Level.parse(levelString);
isQuiet = false;
}
loggers.put(name, new LoggerInfo(level, isQuiet));
}
} catch (final IllegalArgumentException | SecurityException e) {
throw e;
}
}
private static String lastPart(final String packageName) {
final String[] parts = packageName.split("\\.");
if (parts.length == 0) {
return packageName;
}
return parts[parts.length - 1];
}
}

View File

@ -48,7 +48,6 @@ import java.util.StringTokenizer;
import java.util.TimeZone;
import java.util.TreeMap;
import java.util.TreeSet;
import jdk.nashorn.internal.runtime.Logging;
import jdk.nashorn.internal.runtime.QuotedStringTokenizer;
/**
@ -532,9 +531,7 @@ public final class Options {
case "keyvalues":
return new KeyValueOption(value);
case "log":
final KeyValueOption kv = new KeyValueOption(value);
Logging.initialize(kv.getValues());
return kv;
return new LoggingOption(value);
case "boolean":
return new Option<>(value != null && Boolean.parseBoolean(value));
case "integer":

View File

@ -178,7 +178,6 @@ public class Shell {
*
* @return null if there are problems with option parsing.
*/
@SuppressWarnings("resource")
private static Context makeContext(final InputStream in, final OutputStream out, final OutputStream err, final String[] args) {
final PrintStream pout = out instanceof PrintStream ? (PrintStream) out : new PrintStream(out);
final PrintStream perr = err instanceof PrintStream ? (PrintStream) err : new PrintStream(err);
@ -392,7 +391,6 @@ public class Shell {
* @param global global scope object to use
* @return return code
*/
@SuppressWarnings("resource")
private static int readEvalPrint(final Context context, final Global global) {
final String prompt = bundle.getString("shell.prompt");
final BufferedReader in = new BufferedReader(new InputStreamReader(System.in));

View File

@ -50,7 +50,7 @@ public class ParserTest {
public boolean exclude(File file, String content);
}
private void log(String msg) {
private static void log(final String msg) {
org.testng.Reporter.log(msg, true);
}
@ -63,7 +63,7 @@ public class ParserTest {
options.set("parse.only", true);
options.set("scripting", true);
ErrorManager errors = new ErrorManager();
final ErrorManager errors = new ErrorManager();
this.context = new Context(options, errors, Thread.currentThread().getContextClassLoader());
}
@ -153,7 +153,7 @@ public class ParserTest {
}
};
errors.setLimit(0);
final Source source = new Source(file.getAbsolutePath(), buffer);
final Source source = new Source(file.getAbsolutePath(), buffer);
new Parser(context.getEnv(), source, errors, context.getEnv()._strict).parse();
if (errors.getNumberOfErrors() > 0) {
log("Parse failed: " + file.getAbsolutePath());
@ -162,6 +162,7 @@ public class ParserTest {
passed++;
}
} catch (final Throwable exp) {
exp.printStackTrace();
log("Parse failed: " + file.getAbsolutePath() + " : " + exp);
if (VERBOSE) {
exp.printStackTrace(System.out);

View File

@ -149,7 +149,7 @@ public class ParallelTestRunner {
}
@Override
protected void log(String msg) {
protected void log(final String msg) {
System.err.println(msg);
}
@ -235,6 +235,7 @@ public class ParallelTestRunner {
outputFile.write(out.toByteArray());
errorFile.write(err.toByteArray());
}
ex.printStackTrace();
throw ex;
}
}
@ -280,6 +281,7 @@ public class ParallelTestRunner {
} catch (final Throwable ex) {
result.exception = ex;
result.passed = false;
ex.printStackTrace();
}
return result;
}
@ -306,12 +308,12 @@ public class ParallelTestRunner {
final TestFactory<ScriptRunnable> testFactory = new TestFactory<ScriptRunnable>() {
@Override
public ScriptRunnable createTest(String framework, File testFile, List<String> engineOptions, Map<String, String> testOptions, List<String> arguments) {
public ScriptRunnable createTest(final String framework, final File testFile, final List<String> engineOptions, final Map<String, String> testOptions, final List<String> arguments) {
return new ScriptRunnable(framework, testFile, engineOptions, testOptions, arguments);
}
@Override
public void log(String msg) {
public void log(final String msg) {
System.err.println(msg);
}
};
@ -431,7 +433,9 @@ public class ParallelTestRunner {
public static void main(final String[] args) throws Exception {
parseArgs(args);
while(new ParallelTestRunner().run());
while(new ParallelTestRunner().run()) {
;
}
}
private static void parseArgs(final String[] args) {