# HG changeset patch # User lagergren # Date 1398262427 -7200 # Node ID 5290da85fc3dc8e310366ed4ab95dc6837e8277c # Parent 138ee369abd83651f159adfa5f5787c9212b5c01 8038426: Move all loggers from process wide scope into Global scope Reviewed-by: attila, hannesw diff -r 138ee369abd8 -r 5290da85fc3d nashorn/src/jdk/nashorn/internal/codegen/ApplySpecialization.java --- a/nashorn/src/jdk/nashorn/internal/codegen/ApplySpecialization.java Tue Apr 22 14:09:46 2014 +0200 +++ b/nashorn/src/jdk/nashorn/internal/codegen/ApplySpecialization.java Wed Apr 23 16:13:47 2014 +0200 @@ -45,7 +45,9 @@ 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 @@ * */ -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 @@ private final MethodType actualCallSiteType; - private static final DebugLogger LOG = new DebugLogger("apply2call"); + private final DebugLogger log; private static final String ARGUMENTS = ARGUMENTS_VAR.symbolName(); @@ -99,14 +102,6 @@ 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 * "arguments" doesn't escape. @@ -116,9 +111,20 @@ * @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 @@ } }); } 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 @@ 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 @@ 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 @@ 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(); } diff -r 138ee369abd8 -r 5290da85fc3d nashorn/src/jdk/nashorn/internal/codegen/Attr.java --- a/nashorn/src/jdk/nashorn/internal/codegen/Attr.java Tue Apr 22 14:09:46 2014 +0200 +++ b/nashorn/src/jdk/nashorn/internal/codegen/Attr.java Wed Apr 23 16:13:47 2014 +0200 @@ -59,6 +59,7 @@ import java.util.List; import java.util.Map; import java.util.Set; + import jdk.nashorn.internal.codegen.types.Type; import jdk.nashorn.internal.ir.AccessNode; import jdk.nashorn.internal.ir.BinaryNode; @@ -99,13 +100,16 @@ 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 @@ * but in general, this is where the main symbol type information is * computed. */ - -final class Attr extends NodeOperatorVisitor { +@Logger(name="Attr") +final class Attr extends NodeOperatorVisitor implements Loggable { private final CompilationEnvironment env; @@ -146,8 +150,8 @@ 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 @@ 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 @@ 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 @@ 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 @@ //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 @@ // 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 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 @@ // 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 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 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 @@ } 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 @@ */ 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 @@ 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 @@ 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 @@ } 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 @@ } 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 @@ 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 @@ } 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 @@ append(" in '"). append(lc.getCurrentFunction().getName()). append("'"); - LOG.info(sb); - LOG.indent(); + log.info(sb); + log.indent(); } return true; @@ -2256,7 +2272,7 @@ // 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 @@ } } - LOG.unindent(); - LOG.info(sb); + log.unindent(); + log.info(sb); } return node; diff -r 138ee369abd8 -r 5290da85fc3d nashorn/src/jdk/nashorn/internal/codegen/CodeGenerator.java --- a/nashorn/src/jdk/nashorn/internal/codegen/CodeGenerator.java Tue Apr 22 14:09:46 2014 +0200 +++ b/nashorn/src/jdk/nashorn/internal/codegen/CodeGenerator.java Wed Apr 23 16:13:47 2014 +0200 @@ -133,7 +133,6 @@ 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.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 @@ * The CodeGenerator visits nodes only once, tags them as resolved and emits * bytecode for them. */ -final class CodeGenerator extends NodeOperatorVisitor { +@Logger(name="codegen") +final class CodeGenerator extends NodeOperatorVisitor implements Loggable { private static final Type SCOPE_TYPE = Type.typeFor(ScriptObject.class); @@ -214,7 +217,7 @@ /** 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 @@ 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 @@ // 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 @@ 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; } diff -r 138ee369abd8 -r 5290da85fc3d nashorn/src/jdk/nashorn/internal/codegen/CompilationPhase.java --- a/nashorn/src/jdk/nashorn/internal/codegen/CompilationPhase.java Tue Apr 22 14:09:46 2014 +0200 +++ b/nashorn/src/jdk/nashorn/internal/codegen/CompilationPhase.java Wed Apr 23 16:13:47 2014 +0200 @@ -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.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 @@ 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 @@ 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 @@ compiler.getCodeInstaller().verify(bytecode); } - DumpBytecode.dumpBytecode(env, bytecode, className); + DumpBytecode.dumpBytecode(env, compiler, bytecode, className); } return newFunctionNode; diff -r 138ee369abd8 -r 5290da85fc3d nashorn/src/jdk/nashorn/internal/codegen/Compiler.java --- a/nashorn/src/jdk/nashorn/internal/codegen/Compiler.java Tue Apr 22 14:09:46 2014 +0200 +++ b/nashorn/src/jdk/nashorn/internal/codegen/Compiler.java Wed Apr 23 16:13:47 2014 +0200 @@ -51,6 +51,7 @@ 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.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 @@ * 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 @@ /** 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 @@ 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 @@ 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 @@ append(" Total size = "). append(totalSize / 1024 / 1024). append("MB"); - LOG.info(sb); + log.info(sb); Collections.sort(list, new Comparator() { @Override @@ -212,9 +225,9 @@ }); 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 @@ 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 @@ append(" ms "); } - LOG.fine(sb); + log.fine(sb); } } @@ -305,14 +318,14 @@ 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 @@ } final StringBuilder sb; - if (LOG.isEnabled()) { + if (log.isEnabled()) { sb = new StringBuilder(); sb.append("Installed class '"). append(rootClass.getSimpleName()). @@ -408,7 +421,7 @@ } if (sb != null) { - LOG.fine(sb); + log.fine(sb); } return rootClass; @@ -482,7 +495,7 @@ 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 @@ 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); - } } diff -r 138ee369abd8 -r 5290da85fc3d nashorn/src/jdk/nashorn/internal/codegen/DumpBytecode.java --- a/nashorn/src/jdk/nashorn/internal/codegen/DumpBytecode.java Tue Apr 22 14:09:46 2014 +0200 +++ b/nashorn/src/jdk/nashorn/internal/codegen/DumpBytecode.java Wed Apr 23 16:13:47 2014 +0200 @@ -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 @@ * 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 @@ 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 @@ 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( diff -r 138ee369abd8 -r 5290da85fc3d nashorn/src/jdk/nashorn/internal/codegen/FinalizeTypes.java --- a/nashorn/src/jdk/nashorn/internal/codegen/FinalizeTypes.java Tue Apr 22 14:09:46 2014 +0200 +++ b/nashorn/src/jdk/nashorn/internal/codegen/FinalizeTypes.java Wed Apr 23 16:13:47 2014 +0200 @@ -42,9 +42,12 @@ 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 @@ * that scope and slot information is correct. This enables e.g. AccessSpecialization * and frame optimizations */ +@Logger(name="finalize") +final class FinalizeTypes extends NodeOperatorVisitor implements Loggable { -final class FinalizeTypes extends NodeOperatorVisitor { - - 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 @@ 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"); } } } diff -r 138ee369abd8 -r 5290da85fc3d nashorn/src/jdk/nashorn/internal/codegen/FindScopeDepths.java --- a/nashorn/src/jdk/nashorn/internal/codegen/FindScopeDepths.java Tue Apr 22 14:09:46 2014 +0200 +++ b/nashorn/src/jdk/nashorn/internal/codegen/FindScopeDepths.java Wed Apr 23 16:13:47 2014 +0200 @@ -42,9 +42,12 @@ 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 @@ * stored in the RecompilableScriptFunctionData and is transferred to the * FunctionNode being compiled */ - -final class FindScopeDepths extends NodeVisitor { +@Logger(name="scopedepths") +final class FindScopeDepths extends NodeVisitor implements Loggable { private final Compiler compiler; private final CompilationEnvironment env; @@ -61,12 +64,23 @@ private final Map> externalSymbolDepths = new HashMap<>(); private final Map> 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 @@ 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; diff -r 138ee369abd8 -r 5290da85fc3d nashorn/src/jdk/nashorn/internal/codegen/FoldConstants.java --- a/nashorn/src/jdk/nashorn/internal/codegen/FoldConstants.java Tue Apr 22 14:09:46 2014 +0200 +++ b/nashorn/src/jdk/nashorn/internal/codegen/FoldConstants.java Wed Apr 23 16:13:47 2014 +0200 @@ -27,6 +27,7 @@ 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.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 { +@Logger(name="fold") +final class FoldConstants extends NodeVisitor 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 @@ 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 LexicalContext lc = new LexicalContext(); block.accept(lc, new NodeVisitor(lc) { @Override - public boolean enterVarNode(VarNode varNode) { + public boolean enterVarNode(final VarNode varNode) { statements.add(varNode.setInit(null)); return false; } @@ -256,7 +272,7 @@ 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; diff -r 138ee369abd8 -r 5290da85fc3d nashorn/src/jdk/nashorn/internal/codegen/Lower.java --- a/nashorn/src/jdk/nashorn/internal/codegen/Lower.java Tue Apr 22 14:09:46 2014 +0200 +++ b/nashorn/src/jdk/nashorn/internal/codegen/Lower.java Wed Apr 23 16:13:47 2014 +0200 @@ -34,6 +34,7 @@ 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.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 @@ * harder and context dependent to do any code copying after symbols have been * finalized. */ +@Logger(name="lower") +final class Lower extends NodeOperatorVisitor implements Loggable { -final class Lower extends NodeOperatorVisitor { - - 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 @@ 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 @@ } @Override - public Node leaveBlockStatement(BlockStatement blockStatement) { + public Node leaveBlockStatement(final BlockStatement blockStatement) { return addStatement(blockStatement); } @@ -252,7 +268,7 @@ @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 @@ 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 @@ * @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(); diff -r 138ee369abd8 -r 5290da85fc3d nashorn/src/jdk/nashorn/internal/codegen/MethodEmitter.java --- a/nashorn/src/jdk/nashorn/internal/codegen/MethodEmitter.java Tue Apr 22 14:09:46 2014 +0200 +++ b/nashorn/src/jdk/nashorn/internal/codegen/MethodEmitter.java Wed Apr 23 16:13:47 2014 +0200 @@ -98,12 +98,12 @@ 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 @@ 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 @@ * @param args debug information to print */ private void debug(final Object... args) { - if (DEBUG) { + if (debug) { debug(30, args); } } @@ -2313,13 +2313,13 @@ * @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 @@ } 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()); } } } diff -r 138ee369abd8 -r 5290da85fc3d nashorn/src/jdk/nashorn/internal/codegen/ObjectClassGenerator.java --- a/nashorn/src/jdk/nashorn/internal/codegen/ObjectClassGenerator.java Tue Apr 22 14:09:46 2014 +0200 +++ b/nashorn/src/jdk/nashorn/internal/codegen/ObjectClassGenerator.java Wed Apr 23 16:13:47 2014 +0200 @@ -50,30 +50,30 @@ 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 @@ * 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"); - - /** - * Get the field logger - * @return logger - */ - public static DebugLogger getLogger() { - return LOG; - } + private final DebugLogger log; - private static final Set FIELDS_TO_INSTRUMENT; - static { - final String fields = Options.getStringProperty("nashorn.fields", null); - final Set 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 @@ 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 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()); } /** diff -r 138ee369abd8 -r 5290da85fc3d nashorn/src/jdk/nashorn/internal/codegen/RangeAnalyzer.java --- a/nashorn/src/jdk/nashorn/internal/codegen/RangeAnalyzer.java Tue Apr 22 14:09:46 2014 +0200 +++ b/nashorn/src/jdk/nashorn/internal/codegen/RangeAnalyzer.java Wed Apr 23 16:13:47 2014 +0200 @@ -47,8 +47,11 @@ 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 @@ * * Proves that the multiplication never exceeds 24 bits and can thus be an int */ -final class RangeAnalyzer extends NodeOperatorVisitor { - static final DebugLogger LOG = new DebugLogger("ranges"); +@Logger(name="ranges") +final class RangeAnalyzer extends NodeOperatorVisitor implements Loggable { + private final DebugLogger log; - private static final Range.Functionality RANGE = new Range.Functionality(LOG); + private final Range.Functionality func; private final Map 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 @@ //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 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 @@ } 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 @@ @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 @@ @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 @@ @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 @@ 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 @@ @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 @@ * @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 @@ 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: diff -r 138ee369abd8 -r 5290da85fc3d nashorn/src/jdk/nashorn/internal/codegen/Splitter.java --- a/nashorn/src/jdk/nashorn/internal/codegen/Splitter.java Tue Apr 22 14:09:46 2014 +0200 +++ b/nashorn/src/jdk/nashorn/internal/codegen/Splitter.java Wed Apr 23 16:13:47 2014 +0200 @@ -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.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 @@ /** 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 @@ this.compiler = compiler; this.outermost = functionNode; this.outermostCompileUnit = outermostCompileUnit; + this.log = compiler.getLogger(); } /** @@ -86,7 +90,7 @@ 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 @@ 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()) { diff -r 138ee369abd8 -r 5290da85fc3d nashorn/src/jdk/nashorn/internal/codegen/types/Range.java --- a/nashorn/src/jdk/nashorn/internal/codegen/types/Range.java Tue Apr 22 14:09:46 2014 +0200 +++ b/nashorn/src/jdk/nashorn/internal/codegen/types/Range.java Wed Apr 23 16:13:47 2014 +0200 @@ -29,7 +29,7 @@ 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 @@ 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); diff -r 138ee369abd8 -r 5290da85fc3d nashorn/src/jdk/nashorn/internal/ir/IdentNode.java --- a/nashorn/src/jdk/nashorn/internal/ir/IdentNode.java Tue Apr 22 14:09:46 2014 +0200 +++ b/nashorn/src/jdk/nashorn/internal/ir/IdentNode.java Wed Apr 23 16:13:47 2014 +0200 @@ -28,9 +28,6 @@ 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 @@ 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); } diff -r 138ee369abd8 -r 5290da85fc3d nashorn/src/jdk/nashorn/internal/lookup/MethodHandleFactory.java --- a/nashorn/src/jdk/nashorn/internal/lookup/MethodHandleFactory.java Tue Apr 22 14:09:46 2014 +0200 +++ b/nashorn/src/jdk/nashorn/internal/lookup/MethodHandleFactory.java Wed Apr 23 16:13:47 2014 +0200 @@ -37,9 +37,12 @@ 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 @@ 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 @@ 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 @@ } /** - * 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 { - - @Override - public MethodHandle filterArguments(final MethodHandle target, final int pos, final MethodHandle... filters) { - return MethodHandles.filterArguments(target, pos, filters); - } - - @Override - public MethodHandle filterReturnValue(final MethodHandle target, final MethodHandle filter) { - return MethodHandles.filterReturnValue(target, filter); - } - - @Override - public MethodHandle guardWithTest(final MethodHandle test, final MethodHandle target, final MethodHandle fallback) { - return MethodHandles.guardWithTest(test, target, fallback); - } - - @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> 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); - } + @Logger(name="methodhandles") + private static class StandardMethodHandleFunctionality implements MethodHandleFunctionality, Loggable { - @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); - } + // 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; - @Override - public MethodHandle throwException(final Class returnType, final Class exType) { - return MethodHandles.throwException(returnType, exType); - } - - @Override - public MethodHandle catchException(final MethodHandle target, final Class 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); + public StandardMethodHandleFunctionality() { } @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); - } + public DebugLogger initLogger(final Global global) { + return this.log = global.getLogger(this.getClass()); } @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); - } + public DebugLogger getLogger() { + return log; } - @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 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> 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 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 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; - } - } } diff -r 138ee369abd8 -r 5290da85fc3d nashorn/src/jdk/nashorn/internal/lookup/MethodHandleFunctionality.java --- a/nashorn/src/jdk/nashorn/internal/lookup/MethodHandleFunctionality.java Tue Apr 22 14:09:46 2014 +0200 +++ b/nashorn/src/jdk/nashorn/internal/lookup/MethodHandleFunctionality.java Wed Apr 23 16:13:47 2014 +0200 @@ -337,5 +337,6 @@ * @return the method type */ public MethodType type(Class returnType, Class... paramTypes); + } diff -r 138ee369abd8 -r 5290da85fc3d nashorn/src/jdk/nashorn/internal/objects/Global.java --- a/nashorn/src/jdk/nashorn/internal/objects/Global.java Tue Apr 22 14:09:46 2014 +0200 +++ b/nashorn/src/jdk/nashorn/internal/objects/Global.java Wed Apr 23 16:13:47 2014 +0200 @@ -44,12 +44,15 @@ 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.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 @@ // context to which this global belongs to private final Context context; + // logging + private final Map loggers = new HashMap<>(); + + private void initLoggers() { + ((Loggable)MethodHandleFactory.getFunctionality()).initLogger(this); + } + @Override protected Context getContext() { return context; @@ -465,7 +479,8 @@ this.context = context; this.setIsScope(); this.optimisticFunctionMap = new HashMap<>(); - GlobalConstants.instance().invalidateAll(); + final GlobalConstants gc = GlobalConstants.instance(this); + gc.invalidateAll(); } /** @@ -480,6 +495,14 @@ } /** + * 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} * * @return the script environment @@ -1691,6 +1714,8 @@ // synonym for "arguments" in scripting mode addOwnProperty("$ARG", argumentsFlags, argumentsObject); } + + initLoggers(); } private void initErrorObjects() { @@ -2072,7 +2097,7 @@ 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 @@ 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 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 clazz, final MethodHandle mh, final Supplier 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 clazz, final Level level, final MethodHandle mh, final int paramStart, final boolean printReturnValue, final Supplier 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; + } + } diff -r 138ee369abd8 -r 5290da85fc3d nashorn/src/jdk/nashorn/internal/parser/Parser.java --- a/nashorn/src/jdk/nashorn/internal/parser/Parser.java Tue Apr 22 14:09:46 2014 +0200 +++ b/nashorn/src/jdk/nashorn/internal/parser/Parser.java Wed Apr 23 16:13:47 2014 +0200 @@ -105,7 +105,7 @@ import jdk.nashorn.internal.ir.VarNode; import jdk.nashorn.internal.ir.WhileNode; import jdk.nashorn.internal.ir.WithNode; -import jdk.nashorn.internal.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.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 @@ /** 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 @@ // 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 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 @@ 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 @@ return nodeList; } - private static List optimizeList(ArrayList list) { + private static List optimizeList(final ArrayList list) { switch(list.size()) { case 0: { return Collections.emptyList(); @@ -2668,7 +2684,7 @@ 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; } diff -r 138ee369abd8 -r 5290da85fc3d nashorn/src/jdk/nashorn/internal/runtime/AccessorProperty.java --- a/nashorn/src/jdk/nashorn/internal/runtime/AccessorProperty.java Tue Apr 22 14:09:46 2014 +0200 +++ b/nashorn/src/jdk/nashorn/internal/runtime/AccessorProperty.java Wed Apr 23 16:13:47 2014 +0200 @@ -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 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 @@ */ 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 @@ 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 @@ // 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 @@ 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 @@ */ 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 @@ 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 @@ return currentType; } - private static MethodHandle findOwnMH(final String name, final Class rtype, final Class... 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() { + @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() { + @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() { + @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() { + @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)); } - } diff -r 138ee369abd8 -r 5290da85fc3d nashorn/src/jdk/nashorn/internal/runtime/CompiledFunction.java --- a/nashorn/src/jdk/nashorn/internal/runtime/CompiledFunction.java Tue Apr 22 14:09:46 2014 +0200 +++ b/nashorn/src/jdk/nashorn/internal/runtime/CompiledFunction.java Wed Apr 23 16:13:47 2014 +0200 @@ -41,8 +41,10 @@ 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 @@ 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 @@ 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 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 @@ //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 @@ private final RecompilableScriptFunctionData data; private final Map 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 @@ 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 }); diff -r 138ee369abd8 -r 5290da85fc3d nashorn/src/jdk/nashorn/internal/runtime/Context.java --- a/nashorn/src/jdk/nashorn/internal/runtime/Context.java Tue Apr 22 14:09:46 2014 +0200 +++ b/nashorn/src/jdk/nashorn/internal/runtime/Context.java Wed Apr 23 16:13:47 2014 +0200 @@ -65,6 +65,7 @@ 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 @@ // 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 @@ 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; } diff -r 138ee369abd8 -r 5290da85fc3d nashorn/src/jdk/nashorn/internal/runtime/DebugLogger.java --- a/nashorn/src/jdk/nashorn/internal/runtime/DebugLogger.java Tue Apr 22 14:09:46 2014 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,546 +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.io.PrintWriter; -import java.util.logging.Level; -import java.util.logging.Logger; - -import jdk.nashorn.internal.objects.Global; -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 { - private final Logger logger; - private final boolean isEnabled; - - private int indent; - - private static final int INDENT_SPACE = 4; - - /** 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 - */ - 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); - assert logger != null; - this.isEnabled = getLevel() != Level.OFF; - } - - /** - * Do not currently support chaining this with parent logger. Logger level null - * means disabled - * @return level - */ - private Level getLevel() { - return logger.getLevel() == null ? Level.OFF : logger.getLevel(); - } - - /** - * Get the output writer for the logger. Loggers always default to - * stderr for output as they are used mainly to output debug info - * - * Can be inherited so this should not be static. - * - * @return print writer for log output. - */ - @SuppressWarnings("static-method") - public PrintWriter getOutputStream() { - return Context.getCurrentErr(); - } - - /** - * Add quotes around a string - * @param str string - * @return quoted string - */ - public static String quote(final String str) { - if (str.isEmpty()) { - return "''"; - } - - char startQuote = '\0'; - char endQuote = '\0'; - char quote = '\0'; - - if (str.startsWith("\\") || str.startsWith("\"")) { - startQuote = str.charAt(0); - } - if (str.endsWith("\\") || str.endsWith("\"")) { - endQuote = str.charAt(str.length() - 1); - } - - if (startQuote == '\0' || endQuote == '\0') { - quote = startQuote == '\0' ? endQuote : startQuote; - } - if (quote == '\0') { - quote = '\''; - } - - return (startQuote == '\0' ? quote : startQuote) + str + (endQuote == '\0' ? quote : endQuote); - } - - /** - * Check if the logger is enabled - * @return true if enabled - */ - public boolean isEnabled() { - return isEnabled; - } - - /** - * If you want to change the indent level of your logger, call indent with a new position. - * Positions start at 0 and are increased by one for a new "tab" - * - * @param pos indent position - */ - public void indent(final int pos) { - if (isEnabled) { - indent += pos * INDENT_SPACE; - } - } - - /** - * Add an indent position - */ - public void indent() { - indent += INDENT_SPACE; - } - - /** - * Unindent a position - */ - public void unindent() { - indent -= INDENT_SPACE; - if (indent < 0) { - indent = 0; - } - } - - private static void logEvent(final RuntimeEvent event) { - if (event != null) { - final Global global = Context.getGlobal(); - if (global.has("Debug")) { - final ScriptObject debug = (ScriptObject)global.get("Debug"); - final ScriptFunction addRuntimeEvent = (ScriptFunction)debug.get("addRuntimeEvent"); - ScriptRuntime.apply(addRuntimeEvent, debug, event); - } - } - } - - /** - * Check if the logger is above the level of detail given - * @see java.util.logging.Level - * - * The higher the level, the more severe the warning - * - * @param level logging level - * @return true if level is above the given one - */ - public boolean levelCoarserThan(final Level level) { - return getLevel().intValue() > level.intValue(); - } - - /** - * Check if the logger is above or equal to the level - * of detail given - * @see java.util.logging.Level - * - * The higher the level, the more severe the warning - * - * @param level logging level - * @return true if level is above the given one - */ - public boolean levelCoarserThanOrEqual(final Level level) { - return getLevel().intValue() >= level.intValue(); - } - - /** - * Check if the logger is below the level of detail given - * @see java.util.logging.Level - * - * The higher the level, the more severe the warning - * - * @param level logging level - * @return true if level is above the given one - */ - public boolean levelFinerThan(final Level level) { - return getLevel().intValue() < level.intValue(); - } - - /** - * Check if the logger is below or equal to the level - * of detail given - * @see java.util.logging.Level - * - * The higher the level, the more severe the warning - * - * @param level logging level - * @return true if level is above the given one - */ - public boolean levelFinerThanOrEqual(final Level level) { - return getLevel().intValue() <= level.intValue(); - } - - /** - * Shorthand for outputting a log string as log level {@link java.util.logging.Level#FINEST} on this logger - * @param str the string to log - */ - public void finest(final String str) { - log(Level.FINEST, str); - } - - /** - * Shorthand for outputting a log string as log level {@link java.util.logging.Level#FINEST} on this logger - * @param event optional runtime event to log - * @param str the string to log - */ - public void finest(final RuntimeEvent event, final String str) { - finest(str); - logEvent(event); - } - - /** - * Shorthand for outputting a log string as log level - * {@link java.util.logging.Level#FINEST} on this logger - * @param objs object array to log - use this to perform lazy concatenation to avoid unconditional toString overhead - */ - public void finest(final Object... objs) { - log(Level.FINEST, objs); - } - - /** - * Shorthand for outputting a log string as log level - * {@link java.util.logging.Level#FINEST} on this logger - * @param event optional runtime event to log - * @param objs object array to log - use this to perform lazy concatenation to avoid unconditional toString overhead - */ - public void finest(final RuntimeEvent event, final Object... objs) { - finest(objs); - logEvent(event); - } - - /** - * Shorthand for outputting a log string as log level - * {@link java.util.logging.Level#FINER} on this logger - * @param str the string to log - */ - public void finer(final String str) { - log(Level.FINER, str); - } - - /** - * Shorthand for outputting a log string as log level - * {@link java.util.logging.Level#FINER} on this logger - * @param event optional runtime event to log - * @param str the string to log - */ - public void finer(final RuntimeEvent event, final String str) { - finer(str); - logEvent(event); - } - - /** - * Shorthand for outputting a log string as log level - * {@link java.util.logging.Level#FINER} on this logger - * @param objs object array to log - use this to perform lazy concatenation to avoid unconditional toString overhead - */ - public void finer(final Object... objs) { - log(Level.FINER, objs); - } - - /** - * Shorthand for outputting a log string as log level - * {@link java.util.logging.Level#FINER} on this logger - * @param event optional runtime event to log - * @param objs object array to log - use this to perform lazy concatenation to avoid unconditional toString overhead - */ - public void finer(final RuntimeEvent event, final Object... objs) { - finer(objs); - logEvent(event); - } - - /** - * Shorthand for outputting a log string as log level - * {@link java.util.logging.Level#FINE} on this logger - * @param str the string to log - */ - public void fine(final String str) { - log(Level.FINE, str); - } - - /** - * Shorthand for outputting a log string as log level - * {@link java.util.logging.Level#FINE} on this logger - * @param event optional runtime event to log - * @param str the string to log - */ - public void fine(final RuntimeEvent event, final String str) { - fine(str); - logEvent(event); - } - - /** - * Shorthand for outputting a log string as log level - * {@link java.util.logging.Level#FINE} on this logger - * @param objs object array to log - use this to perform lazy concatenation to avoid unconditional toString overhead - */ - public void fine(final Object... objs) { - log(Level.FINE, objs); - } - - /** - * Shorthand for outputting a log string as log level - * {@link java.util.logging.Level#FINE} on this logger - * @param event optional runtime event to log - * @param objs object array to log - use this to perform lazy concatenation to avoid unconditional toString overhead - */ - public void fine(final RuntimeEvent event, final Object... objs) { - fine(objs); - logEvent(event); - } - - /** - * Shorthand for outputting a log string as log level - * {@link java.util.logging.Level#CONFIG} on this logger - * @param str the string to log - */ - public void config(final String str) { - log(Level.CONFIG, str); - } - - /** - * Shorthand for outputting a log string as log level - * {@link java.util.logging.Level#CONFIG} on this logger - * @param event optional runtime event to log - * @param str the string to log - */ - public void config(final RuntimeEvent event, final String str) { - config(str); - logEvent(event); - } - - /** - * Shorthand for outputting a log string as log level - * {@link java.util.logging.Level#CONFIG} on this logger - * @param objs object array to log - use this to perform lazy concatenation to avoid unconditional toString overhead - */ - public void config(final Object... objs) { - log(Level.CONFIG, objs); - } - - /** - * Shorthand for outputting a log string as log level - * {@link java.util.logging.Level#CONFIG} on this logger - * @param event optional runtime event to log - * @param objs object array to log - use this to perform lazy concatenation to avoid unconditional toString overhead - */ - public void config(final RuntimeEvent event, final Object... objs) { - config(objs); - logEvent(event); - } - - /** - * Shorthand for outputting a log string as log level - * {@link java.util.logging.Level#INFO} on this logger - * @param str the string to log - */ - public void info(final String str) { - log(Level.INFO, str); - } - - /** - * Shorthand for outputting a log string as log level - * {@link java.util.logging.Level#INFO} on this logger - * @param event optional runtime event to log - * @param str the string to log - */ - public void info(final RuntimeEvent event, final String str) { - info(str); - logEvent(event); - } - - /** - * Shorthand for outputting a log string as log level - * {@link java.util.logging.Level#FINE} on this logger - * @param objs object array to log - use this to perform lazy concatenation to avoid unconditional toString overhead - */ - public void info(final Object... objs) { - log(Level.INFO, objs); - } - - /** - * Shorthand for outputting a log string as log level - * {@link java.util.logging.Level#FINE} on this logger - * @param event optional runtime event to log - * @param objs object array to log - use this to perform lazy concatenation to avoid unconditional toString overhead - */ - public void info(final RuntimeEvent event, final Object... objs) { - info(objs); - logEvent(event); - } - - /** - * Shorthand for outputting a log string as log level - * {@link java.util.logging.Level#WARNING} on this logger - * @param str the string to log - */ - public void warning(final String str) { - log(Level.WARNING, str); - } - - /** - * Shorthand for outputting a log string as log level - * {@link java.util.logging.Level#WARNING} on this logger - * @param event optional runtime event to log - * @param str the string to log - */ - public void warning(final RuntimeEvent event, final String str) { - warning(str); - logEvent(event); - } - - /** - * Shorthand for outputting a log string as log level - * {@link java.util.logging.Level#FINE} on this logger - * @param objs object array to log - use this to perform lazy concatenation to avoid unconditional toString overhead - */ - public void warning(final Object... objs) { - log(Level.WARNING, objs); - } - - /** - * Shorthand for outputting a log string as log level - * {@link java.util.logging.Level#FINE} on this logger - * @param objs object array to log - use this to perform lazy concatenation to avoid unconditional toString overhead - * @param event optional runtime event to log - */ - public void warning(final RuntimeEvent event, final Object... objs) { - warning(objs); - logEvent(event); - } - - /** - * Shorthand for outputting a log string as log level - * {@link java.util.logging.Level#SEVERE} on this logger - * @param str the string to log - */ - public void severe(final String str) { - log(Level.SEVERE, str); - } - - /** - * Shorthand for outputting a log string as log level - * {@link java.util.logging.Level#SEVERE} on this logger - * @param str the string to log - * @param event optional runtime event to log - */ - public void severe(final RuntimeEvent event, final String str) { - severe(str); - logEvent(event); - } - - /** - * Shorthand for outputting a log string as log level - * {@link java.util.logging.Level#FINE} on this logger - * @param objs object array to log - use this to perform lazy concatenation to avoid unconditional toString overhead - */ - public void severe(final Object... objs) { - log(Level.SEVERE, objs); - } - - /** - * Shorthand for outputting a log string as log level - * {@link java.util.logging.Level#FINE} on this logger - * @param event optional runtime event to log - * @param objs object array to log - use this to perform lazy concatenation to avoid unconditional toString overhead - */ - public void severe(final RuntimeEvent event, final Object... objs) { - severe(objs); - logEvent(event); - } - - /** - * Output log line on this logger at a given level of verbosity - * @see java.util.logging.Level - * - * @param level minimum log level required for logging to take place - * @param str string to log - */ - public void log(final Level level, final String str) { - if (isEnabled && !isQuiet) { - final StringBuilder sb = new StringBuilder(); - for (int i = 0 ; i < indent ; i++) { - sb.append(' '); - } - sb.append(str); - logger.log(level, sb.toString()); - } - } - - /** - * Output log line on this logger at a given level of verbosity - * @see java.util.logging.Level - * - * @param level minimum log level required for logging to take place - * @param objs objects for which to invoke toString and concatenate to log - */ - public void log(final Level level, final Object... objs) { - if (isEnabled && !isQuiet) { - final StringBuilder sb = new StringBuilder(); - for (final Object obj : objs) { - sb.append(obj); - } - log(level, sb.toString()); - } - } -} diff -r 138ee369abd8 -r 5290da85fc3d nashorn/src/jdk/nashorn/internal/runtime/GlobalConstants.java --- a/nashorn/src/jdk/nashorn/internal/runtime/GlobalConstants.java Tue Apr 22 14:09:46 2014 +0200 +++ b/nashorn/src/jdk/nashorn/internal/runtime/GlobalConstants.java Wed Apr 23 16:13:47 2014 +0200 @@ -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.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 @@ * 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 @@ 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 @@ */ private final Map 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 @@ * 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 @@ * @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 @@ 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 @@ 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 @@ 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); diff -r 138ee369abd8 -r 5290da85fc3d nashorn/src/jdk/nashorn/internal/runtime/Logging.java --- a/nashorn/src/jdk/nashorn/internal/runtime/Logging.java Tue Apr 22 14:09:46 2014 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -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() { - @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 loggers = new HashMap<>(); - - private static final Set 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 map) throws IllegalArgumentException { - try { - for (final Entry 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; - } - -} diff -r 138ee369abd8 -r 5290da85fc3d nashorn/src/jdk/nashorn/internal/runtime/PropertyHashMap.java --- a/nashorn/src/jdk/nashorn/internal/runtime/PropertyHashMap.java Tue Apr 22 14:09:46 2014 +0200 +++ b/nashorn/src/jdk/nashorn/internal/runtime/PropertyHashMap.java Wed Apr 23 16:13:47 2014 +0200 @@ -172,7 +172,6 @@ */ 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); } diff -r 138ee369abd8 -r 5290da85fc3d nashorn/src/jdk/nashorn/internal/runtime/RecompilableScriptFunctionData.java --- a/nashorn/src/jdk/nashorn/internal/runtime/RecompilableScriptFunctionData.java Tue Apr 22 14:09:46 2014 +0200 +++ b/nashorn/src/jdk/nashorn/internal/runtime/RecompilableScriptFunctionData.java Wed Apr 23 16:13:47 2014 +0200 @@ -50,9 +50,13 @@ 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 @@ * 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 @@ /** 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 externalScopeDepths; @@ -174,6 +171,18 @@ 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 @@ } MethodHandle compileRestOfMethod(final MethodType fnCallSiteType, final Map 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 @@ 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)); diff -r 138ee369abd8 -r 5290da85fc3d nashorn/src/jdk/nashorn/internal/runtime/ScriptEnvironment.java --- a/nashorn/src/jdk/nashorn/internal/runtime/ScriptEnvironment.java Tue Apr 22 14:09:46 2014 +0200 +++ b/nashorn/src/jdk/nashorn/internal/runtime/ScriptEnvironment.java Wed Apr 23 16:13:47 2014 +0200 @@ -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 @@ /** Local for error messages */ public final Locale _locale; + /** Logging */ + public final Map _loggers; + /** * Constructor * @@ -310,6 +318,9 @@ } else { this._locale = Locale.getDefault(); } + + final LoggingOption lo = (LoggingOption)options.get("log"); + this._loggers = lo == null ? new HashMap() : lo.getLoggers(); } /** @@ -367,4 +378,15 @@ 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; + } + } diff -r 138ee369abd8 -r 5290da85fc3d nashorn/src/jdk/nashorn/internal/runtime/ScriptFunction.java --- a/nashorn/src/jdk/nashorn/internal/runtime/ScriptFunction.java Tue Apr 22 14:09:46 2014 +0200 +++ b/nashorn/src/jdk/nashorn/internal/runtime/ScriptFunction.java Wed Apr 23 16:13:47 2014 +0200 @@ -681,7 +681,7 @@ if (isApplyToCall) { if (isFailedApplyToCall) { //take the real arguments that were passed to a call and force them into the apply instead - 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); diff -r 138ee369abd8 -r 5290da85fc3d nashorn/src/jdk/nashorn/internal/runtime/ScriptObject.java --- a/nashorn/src/jdk/nashorn/internal/runtime/ScriptObject.java Tue Apr 22 14:09:46 2014 +0200 +++ b/nashorn/src/jdk/nashorn/internal/runtime/ScriptObject.java Wed Apr 23 16:13:47 2014 +0200 @@ -918,7 +918,7 @@ 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 @@ } } - 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 @@ } 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 @@ 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; } diff -r 138ee369abd8 -r 5290da85fc3d nashorn/src/jdk/nashorn/internal/runtime/arrays/ContinuousArrayData.java --- a/nashorn/src/jdk/nashorn/internal/runtime/arrays/ContinuousArrayData.java Tue Apr 22 14:09:46 2014 +0200 +++ b/nashorn/src/jdk/nashorn/internal/runtime/arrays/ContinuousArrayData.java Wed Apr 23 16:13:47 2014 +0200 @@ -41,18 +41,22 @@ 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 @@ */ 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 @@ } } - 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 @@ } } - 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; diff -r 138ee369abd8 -r 5290da85fc3d nashorn/src/jdk/nashorn/internal/runtime/arrays/TypedArrayData.java --- a/nashorn/src/jdk/nashorn/internal/runtime/arrays/TypedArrayData.java Tue Apr 22 14:09:46 2014 +0200 +++ b/nashorn/src/jdk/nashorn/internal/runtime/arrays/TypedArrayData.java Wed Apr 23 16:13:47 2014 +0200 @@ -190,8 +190,8 @@ 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 @@ 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; diff -r 138ee369abd8 -r 5290da85fc3d nashorn/src/jdk/nashorn/internal/runtime/events/RecompilationEvent.java --- a/nashorn/src/jdk/nashorn/internal/runtime/events/RecompilationEvent.java Tue Apr 22 14:09:46 2014 +0200 +++ b/nashorn/src/jdk/nashorn/internal/runtime/events/RecompilationEvent.java Wed Apr 23 16:13:47 2014 +0200 @@ -27,6 +27,7 @@ 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 @@ * {@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; } diff -r 138ee369abd8 -r 5290da85fc3d nashorn/src/jdk/nashorn/internal/runtime/logging/DebugLogger.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/nashorn/src/jdk/nashorn/internal/runtime/logging/DebugLogger.java Wed Apr 23 16:13:47 2014 +0200 @@ -0,0 +1,598 @@ +/* + * 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.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; + +/** + * 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; + + private int indent; + + private static final int INDENT_SPACE = 4; + + /** A quiet logger only logs {@link RuntimeEvent}s and does't output any text, regardless of level */ + private final boolean isQuiet; + + /** + * 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 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 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() { + @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 + */ + public Level getLevel() { + return logger.getLevel() == null ? Level.OFF : logger.getLevel(); + } + + /** + * Get the output writer for the logger. Loggers always default to + * stderr for output as they are used mainly to output debug info + * + * Can be inherited so this should not be static. + * + * @return print writer for log output. + */ + @SuppressWarnings("static-method") + public PrintWriter getOutputStream() { + return Context.getCurrentErr(); + } + + /** + * Add quotes around a string + * @param str string + * @return quoted string + */ + public static String quote(final String str) { + if (str.isEmpty()) { + return "''"; + } + + char startQuote = '\0'; + char endQuote = '\0'; + char quote = '\0'; + + if (str.startsWith("\\") || str.startsWith("\"")) { + startQuote = str.charAt(0); + } + if (str.endsWith("\\") || str.endsWith("\"")) { + endQuote = str.charAt(str.length() - 1); + } + + if (startQuote == '\0' || endQuote == '\0') { + quote = startQuote == '\0' ? endQuote : startQuote; + } + if (quote == '\0') { + quote = '\''; + } + + return (startQuote == '\0' ? quote : startQuote) + str + (endQuote == '\0' ? quote : endQuote); + } + + /** + * Check if the logger is enabled + * @return true if enabled + */ + public boolean isEnabled() { + return isEnabled; + } + + /** + * If you want to change the indent level of your logger, call indent with a new position. + * Positions start at 0 and are increased by one for a new "tab" + * + * @param pos indent position + */ + public void indent(final int pos) { + if (isEnabled) { + indent += pos * INDENT_SPACE; + } + } + + /** + * Add an indent position + */ + public void indent() { + indent += INDENT_SPACE; + } + + /** + * Unindent a position + */ + public void unindent() { + indent -= INDENT_SPACE; + if (indent < 0) { + indent = 0; + } + } + + private static void logEvent(final RuntimeEvent event) { + if (event != null) { + final Global global = Context.getGlobal(); + if (global.has("Debug")) { + final ScriptObject debug = (ScriptObject)global.get("Debug"); + final ScriptFunction addRuntimeEvent = (ScriptFunction)debug.get("addRuntimeEvent"); + ScriptRuntime.apply(addRuntimeEvent, debug, event); + } + } + } + + /** + * Check if the logger is above the level of detail given + * @see java.util.logging.Level + * + * The higher the level, the more severe the warning + * + * @param level logging level + * @return true if level is above the given one + */ + public boolean levelCoarserThan(final Level level) { + return getLevel().intValue() > level.intValue(); + } + + /** + * Check if the logger is above or equal to the level + * of detail given + * @see java.util.logging.Level + * + * The higher the level, the more severe the warning + * + * @param level logging level + * @return true if level is above the given one + */ + public boolean levelCoarserThanOrEqual(final Level level) { + return getLevel().intValue() >= level.intValue(); + } + + /** + * Check if the logger is below the level of detail given + * @see java.util.logging.Level + * + * The higher the level, the more severe the warning + * + * @param level logging level + * @return true if level is above the given one + */ + public boolean levelFinerThan(final Level level) { + return getLevel().intValue() < level.intValue(); + } + + /** + * Check if the logger is below or equal to the level + * of detail given + * @see java.util.logging.Level + * + * The higher the level, the more severe the warning + * + * @param level logging level + * @return true if level is above the given one + */ + public boolean levelFinerThanOrEqual(final Level level) { + return getLevel().intValue() <= level.intValue(); + } + + /** + * Shorthand for outputting a log string as log level {@link java.util.logging.Level#FINEST} on this logger + * @param str the string to log + */ + public void finest(final String str) { + log(Level.FINEST, str); + } + + /** + * Shorthand for outputting a log string as log level {@link java.util.logging.Level#FINEST} on this logger + * @param event optional runtime event to log + * @param str the string to log + */ + public void finest(final RuntimeEvent event, final String str) { + finest(str); + logEvent(event); + } + + /** + * Shorthand for outputting a log string as log level + * {@link java.util.logging.Level#FINEST} on this logger + * @param objs object array to log - use this to perform lazy concatenation to avoid unconditional toString overhead + */ + public void finest(final Object... objs) { + log(Level.FINEST, objs); + } + + /** + * Shorthand for outputting a log string as log level + * {@link java.util.logging.Level#FINEST} on this logger + * @param event optional runtime event to log + * @param objs object array to log - use this to perform lazy concatenation to avoid unconditional toString overhead + */ + public void finest(final RuntimeEvent event, final Object... objs) { + finest(objs); + logEvent(event); + } + + /** + * Shorthand for outputting a log string as log level + * {@link java.util.logging.Level#FINER} on this logger + * @param str the string to log + */ + public void finer(final String str) { + log(Level.FINER, str); + } + + /** + * Shorthand for outputting a log string as log level + * {@link java.util.logging.Level#FINER} on this logger + * @param event optional runtime event to log + * @param str the string to log + */ + public void finer(final RuntimeEvent event, final String str) { + finer(str); + logEvent(event); + } + + /** + * Shorthand for outputting a log string as log level + * {@link java.util.logging.Level#FINER} on this logger + * @param objs object array to log - use this to perform lazy concatenation to avoid unconditional toString overhead + */ + public void finer(final Object... objs) { + log(Level.FINER, objs); + } + + /** + * Shorthand for outputting a log string as log level + * {@link java.util.logging.Level#FINER} on this logger + * @param event optional runtime event to log + * @param objs object array to log - use this to perform lazy concatenation to avoid unconditional toString overhead + */ + public void finer(final RuntimeEvent event, final Object... objs) { + finer(objs); + logEvent(event); + } + + /** + * Shorthand for outputting a log string as log level + * {@link java.util.logging.Level#FINE} on this logger + * @param str the string to log + */ + public void fine(final String str) { + log(Level.FINE, str); + } + + /** + * Shorthand for outputting a log string as log level + * {@link java.util.logging.Level#FINE} on this logger + * @param event optional runtime event to log + * @param str the string to log + */ + public void fine(final RuntimeEvent event, final String str) { + fine(str); + logEvent(event); + } + + /** + * Shorthand for outputting a log string as log level + * {@link java.util.logging.Level#FINE} on this logger + * @param objs object array to log - use this to perform lazy concatenation to avoid unconditional toString overhead + */ + public void fine(final Object... objs) { + log(Level.FINE, objs); + } + + /** + * Shorthand for outputting a log string as log level + * {@link java.util.logging.Level#FINE} on this logger + * @param event optional runtime event to log + * @param objs object array to log - use this to perform lazy concatenation to avoid unconditional toString overhead + */ + public void fine(final RuntimeEvent event, final Object... objs) { + fine(objs); + logEvent(event); + } + + /** + * Shorthand for outputting a log string as log level + * {@link java.util.logging.Level#CONFIG} on this logger + * @param str the string to log + */ + public void config(final String str) { + log(Level.CONFIG, str); + } + + /** + * Shorthand for outputting a log string as log level + * {@link java.util.logging.Level#CONFIG} on this logger + * @param event optional runtime event to log + * @param str the string to log + */ + public void config(final RuntimeEvent event, final String str) { + config(str); + logEvent(event); + } + + /** + * Shorthand for outputting a log string as log level + * {@link java.util.logging.Level#CONFIG} on this logger + * @param objs object array to log - use this to perform lazy concatenation to avoid unconditional toString overhead + */ + public void config(final Object... objs) { + log(Level.CONFIG, objs); + } + + /** + * Shorthand for outputting a log string as log level + * {@link java.util.logging.Level#CONFIG} on this logger + * @param event optional runtime event to log + * @param objs object array to log - use this to perform lazy concatenation to avoid unconditional toString overhead + */ + public void config(final RuntimeEvent event, final Object... objs) { + config(objs); + logEvent(event); + } + + /** + * Shorthand for outputting a log string as log level + * {@link java.util.logging.Level#INFO} on this logger + * @param str the string to log + */ + public void info(final String str) { + log(Level.INFO, str); + } + + /** + * Shorthand for outputting a log string as log level + * {@link java.util.logging.Level#INFO} on this logger + * @param event optional runtime event to log + * @param str the string to log + */ + public void info(final RuntimeEvent event, final String str) { + info(str); + logEvent(event); + } + + /** + * Shorthand for outputting a log string as log level + * {@link java.util.logging.Level#FINE} on this logger + * @param objs object array to log - use this to perform lazy concatenation to avoid unconditional toString overhead + */ + public void info(final Object... objs) { + log(Level.INFO, objs); + } + + /** + * Shorthand for outputting a log string as log level + * {@link java.util.logging.Level#FINE} on this logger + * @param event optional runtime event to log + * @param objs object array to log - use this to perform lazy concatenation to avoid unconditional toString overhead + */ + public void info(final RuntimeEvent event, final Object... objs) { + info(objs); + logEvent(event); + } + + /** + * Shorthand for outputting a log string as log level + * {@link java.util.logging.Level#WARNING} on this logger + * @param str the string to log + */ + public void warning(final String str) { + log(Level.WARNING, str); + } + + /** + * Shorthand for outputting a log string as log level + * {@link java.util.logging.Level#WARNING} on this logger + * @param event optional runtime event to log + * @param str the string to log + */ + public void warning(final RuntimeEvent event, final String str) { + warning(str); + logEvent(event); + } + + /** + * Shorthand for outputting a log string as log level + * {@link java.util.logging.Level#FINE} on this logger + * @param objs object array to log - use this to perform lazy concatenation to avoid unconditional toString overhead + */ + public void warning(final Object... objs) { + log(Level.WARNING, objs); + } + + /** + * Shorthand for outputting a log string as log level + * {@link java.util.logging.Level#FINE} on this logger + * @param objs object array to log - use this to perform lazy concatenation to avoid unconditional toString overhead + * @param event optional runtime event to log + */ + public void warning(final RuntimeEvent event, final Object... objs) { + warning(objs); + logEvent(event); + } + + /** + * Shorthand for outputting a log string as log level + * {@link java.util.logging.Level#SEVERE} on this logger + * @param str the string to log + */ + public void severe(final String str) { + log(Level.SEVERE, str); + } + + /** + * Shorthand for outputting a log string as log level + * {@link java.util.logging.Level#SEVERE} on this logger + * @param str the string to log + * @param event optional runtime event to log + */ + public void severe(final RuntimeEvent event, final String str) { + severe(str); + logEvent(event); + } + + /** + * Shorthand for outputting a log string as log level + * {@link java.util.logging.Level#FINE} on this logger + * @param objs object array to log - use this to perform lazy concatenation to avoid unconditional toString overhead + */ + public void severe(final Object... objs) { + log(Level.SEVERE, objs); + } + + /** + * Shorthand for outputting a log string as log level + * {@link java.util.logging.Level#FINE} on this logger + * @param event optional runtime event to log + * @param objs object array to log - use this to perform lazy concatenation to avoid unconditional toString overhead + */ + public void severe(final RuntimeEvent event, final Object... objs) { + severe(objs); + logEvent(event); + } + + /** + * Output log line on this logger at a given level of verbosity + * @see java.util.logging.Level + * + * @param level minimum log level required for logging to take place + * @param str string to log + */ + public void log(final Level level, final String str) { + if (isEnabled && !isQuiet) { + final StringBuilder sb = new StringBuilder(); + for (int i = 0 ; i < indent ; i++) { + sb.append(' '); + } + sb.append(str); + logger.log(level, sb.toString()); + } + } + + /** + * Output log line on this logger at a given level of verbosity + * @see java.util.logging.Level + * + * @param level minimum log level required for logging to take place + * @param objs objects for which to invoke toString and concatenate to log + */ + public void log(final Level level, final Object... objs) { + if (isEnabled && !isQuiet) { + final StringBuilder sb = new StringBuilder(); + for (final Object obj : objs) { + sb.append(obj); + } + 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) }); + } + +} diff -r 138ee369abd8 -r 5290da85fc3d nashorn/src/jdk/nashorn/internal/runtime/logging/Loggable.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/nashorn/src/jdk/nashorn/internal/runtime/logging/Loggable.java Wed Apr 23 16:13:47 2014 +0200 @@ -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(); +} diff -r 138ee369abd8 -r 5290da85fc3d nashorn/src/jdk/nashorn/internal/runtime/logging/Logger.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/nashorn/src/jdk/nashorn/internal/runtime/logging/Logger.java Wed Apr 23 16:13:47 2014 +0200 @@ -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 ""; +} diff -r 138ee369abd8 -r 5290da85fc3d nashorn/src/jdk/nashorn/internal/runtime/options/KeyValueOption.java --- a/nashorn/src/jdk/nashorn/internal/runtime/options/KeyValueOption.java Tue Apr 22 14:09:46 2014 +0200 +++ b/nashorn/src/jdk/nashorn/internal/runtime/options/KeyValueOption.java Wed Apr 23 16:13:47 2014 +0200 @@ -36,7 +36,7 @@ * * {@code --log=module1:level1,module2:level2... } */ -public final class KeyValueOption extends Option { +public class KeyValueOption extends Option { /** * Map of keys given */ diff -r 138ee369abd8 -r 5290da85fc3d nashorn/src/jdk/nashorn/internal/runtime/options/LoggingOption.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/nashorn/src/jdk/nashorn/internal/runtime/options/LoggingOption.java Wed Apr 23 16:13:47 2014 +0200 @@ -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 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 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 logMap) throws IllegalArgumentException { + try { + for (final Entry 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]; + } + + +} diff -r 138ee369abd8 -r 5290da85fc3d nashorn/src/jdk/nashorn/internal/runtime/options/Options.java --- a/nashorn/src/jdk/nashorn/internal/runtime/options/Options.java Tue Apr 22 14:09:46 2014 +0200 +++ b/nashorn/src/jdk/nashorn/internal/runtime/options/Options.java Wed Apr 23 16:13:47 2014 +0200 @@ -48,7 +48,6 @@ 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 @@ 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": diff -r 138ee369abd8 -r 5290da85fc3d nashorn/src/jdk/nashorn/tools/Shell.java --- a/nashorn/src/jdk/nashorn/tools/Shell.java Tue Apr 22 14:09:46 2014 +0200 +++ b/nashorn/src/jdk/nashorn/tools/Shell.java Wed Apr 23 16:13:47 2014 +0200 @@ -178,7 +178,6 @@ * * @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 @@ * @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)); diff -r 138ee369abd8 -r 5290da85fc3d nashorn/test/src/jdk/nashorn/internal/parser/ParserTest.java --- a/nashorn/test/src/jdk/nashorn/internal/parser/ParserTest.java Tue Apr 22 14:09:46 2014 +0200 +++ b/nashorn/test/src/jdk/nashorn/internal/parser/ParserTest.java Wed Apr 23 16:13:47 2014 +0200 @@ -50,7 +50,7 @@ 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 @@ 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 @@ } }; 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 @@ passed++; } } catch (final Throwable exp) { + exp.printStackTrace(); log("Parse failed: " + file.getAbsolutePath() + " : " + exp); if (VERBOSE) { exp.printStackTrace(System.out); diff -r 138ee369abd8 -r 5290da85fc3d nashorn/test/src/jdk/nashorn/internal/test/framework/ParallelTestRunner.java --- a/nashorn/test/src/jdk/nashorn/internal/test/framework/ParallelTestRunner.java Tue Apr 22 14:09:46 2014 +0200 +++ b/nashorn/test/src/jdk/nashorn/internal/test/framework/ParallelTestRunner.java Wed Apr 23 16:13:47 2014 +0200 @@ -149,7 +149,7 @@ } @Override - protected void log(String msg) { + protected void log(final String msg) { System.err.println(msg); } @@ -235,6 +235,7 @@ outputFile.write(out.toByteArray()); errorFile.write(err.toByteArray()); } + ex.printStackTrace(); throw ex; } } @@ -280,6 +281,7 @@ } catch (final Throwable ex) { result.exception = ex; result.passed = false; + ex.printStackTrace(); } return result; } @@ -306,12 +308,12 @@ final TestFactory testFactory = new TestFactory() { @Override - public ScriptRunnable createTest(String framework, File testFile, List engineOptions, Map testOptions, List arguments) { + public ScriptRunnable createTest(final String framework, final File testFile, final List engineOptions, final Map testOptions, final List 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 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) {