8038426: Move all loggers from process wide scope into Global scope
Reviewed-by: attila, hannesw
This commit is contained in:
parent
6163a42a8e
commit
7bb2546460
@ -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();
|
||||
}
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
@ -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(
|
||||
|
@ -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");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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();
|
||||
|
@ -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());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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());
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -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:
|
||||
|
@ -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()) {
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -337,5 +337,6 @@ public interface MethodHandleFunctionality {
|
||||
* @return the method type
|
||||
*/
|
||||
public MethodType type(Class<?> returnType, Class<?>... paramTypes);
|
||||
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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));
|
||||
}
|
||||
}
|
||||
|
@ -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 });
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
}
|
@ -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);
|
||||
}
|
||||
|
@ -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));
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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) });
|
||||
}
|
||||
|
||||
}
|
@ -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();
|
||||
}
|
48
nashorn/src/jdk/nashorn/internal/runtime/logging/Logger.java
Normal file
48
nashorn/src/jdk/nashorn/internal/runtime/logging/Logger.java
Normal 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 "";
|
||||
}
|
@ -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
|
||||
*/
|
||||
|
@ -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];
|
||||
}
|
||||
|
||||
|
||||
}
|
@ -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":
|
||||
|
@ -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));
|
||||
|
@ -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);
|
||||
|
@ -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) {
|
||||
|
Loading…
x
Reference in New Issue
Block a user