8048869: Reduce compile time by about 5% by removing the Class.casts from the AST nodes
Summary: Removed the native casts that slow down the compiler unnecessarily. I also modified the compile-octane harness so that it can run with --verbose and --iterations flags so that you can run the compiler for an arbitrary time, gathering a mission control executing profile.
Reviewed-by: attila, jlaskey
--- a/nashorn/src/jdk/internal/dynalink/support/CompositeTypeBasedGuardingDynamicLinker.java Tue Jul 22 11:55:03 2014 -0700
+++ b/nashorn/src/jdk/internal/dynalink/support/CompositeTypeBasedGuardingDynamicLinker.java Tue Jul 29 14:21:45 2014 -0700
@@ -111,7 +111,7 @@
private final TypeBasedGuardingDynamicLinker[] linkers;
private final List<TypeBasedGuardingDynamicLinker>[] singletonLinkers;
- @SuppressWarnings(value={"unchecked", "rawtypes"})
+ @SuppressWarnings("unchecked")
ClassToLinker(final TypeBasedGuardingDynamicLinker[] linkers) {
this.linkers = linkers;
singletonLinkers = new List[linkers.length];
@@ -135,7 +135,6 @@
case 1: {
list = new LinkedList<>(list);
}
- //$FALL-THROUGH$
default: {
list.add(linker);
}
--- a/nashorn/src/jdk/nashorn/api/scripting/NashornScriptEngine.java Tue Jul 22 11:55:03 2014 -0700
+++ b/nashorn/src/jdk/nashorn/api/scripting/NashornScriptEngine.java Tue Jul 29 14:21:45 2014 -0700
@@ -40,6 +40,7 @@
import java.text.MessageFormat;
import java.util.Locale;
import java.util.ResourceBundle;
+
import javax.script.AbstractScriptEngine;
import javax.script.Bindings;
import javax.script.Compilable;
@@ -50,6 +51,7 @@
import javax.script.ScriptEngineFactory;
import javax.script.ScriptException;
import javax.script.SimpleBindings;
+
import jdk.nashorn.internal.objects.Global;
import jdk.nashorn.internal.runtime.Context;
import jdk.nashorn.internal.runtime.ErrorManager;
@@ -429,7 +431,7 @@
return evalImpl(script, ctxt, getNashornGlobalFrom(ctxt));
}
- private Object evalImpl(final Context.MultiGlobalCompiledScript mgcs, final ScriptContext ctxt, final Global ctxtGlobal) throws ScriptException {
+ private static Object evalImpl(final Context.MultiGlobalCompiledScript mgcs, final ScriptContext ctxt, final Global ctxtGlobal) throws ScriptException {
final Global oldGlobal = Context.getGlobal();
final boolean globalChanged = (oldGlobal != ctxtGlobal);
try {
@@ -450,7 +452,7 @@
}
}
- private Object evalImpl(final ScriptFunction script, final ScriptContext ctxt, final Global ctxtGlobal) throws ScriptException {
+ private static Object evalImpl(final ScriptFunction script, final ScriptContext ctxt, final Global ctxtGlobal) throws ScriptException {
if (script == null) {
return null;
}
--- a/nashorn/src/jdk/nashorn/internal/codegen/CodeGenerator.java Tue Jul 22 11:55:03 2014 -0700
+++ b/nashorn/src/jdk/nashorn/internal/codegen/CodeGenerator.java Tue Jul 29 14:21:45 2014 -0700
@@ -1097,7 +1097,11 @@
closeBlockVariables(block);
lc.releaseSlots();
- assert !method.isReachable() || (lc.isFunctionBody() ? 0 : lc.getUsedSlotCount()) == method.getFirstTemp();
+ assert !method.isReachable() || (lc.isFunctionBody() ? 0 : lc.getUsedSlotCount()) == method.getFirstTemp() :
+ "reachable="+method.isReachable() +
+ " isFunctionBody=" + lc.isFunctionBody() +
+ " usedSlotCount=" + lc.getUsedSlotCount() +
+ " firstTemp=" + method.getFirstTemp();
return block;
}
--- a/nashorn/src/jdk/nashorn/internal/codegen/CompilationPhase.java Tue Jul 22 11:55:03 2014 -0700
+++ b/nashorn/src/jdk/nashorn/internal/codegen/CompilationPhase.java Tue Jul 29 14:21:45 2014 -0700
@@ -43,7 +43,6 @@
import java.util.ArrayList;
import java.util.EnumSet;
import java.util.HashMap;
-import java.util.IdentityHashMap;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
@@ -334,15 +333,15 @@
sb.append("$restOf");
}
newUnit = compiler.createCompileUnit(sb.toString(), oldUnit.getWeight());
- log.info("Creating new compile unit ", oldUnit, " => ", newUnit);
+ log.fine("Creating new compile unit ", oldUnit, " => ", newUnit);
map.put(oldUnit, newUnit);
assert newUnit != null;
newUnits.add(newUnit);
}
- log.info("Replacing compile units in Compiler...");
+ log.fine("Replacing compile units in Compiler...");
compiler.replaceCompileUnits(newUnits);
- log.info("Done");
+ log.fine("Done");
//replace old compile units in function nodes, if any are assigned,
//for example by running the splitter on this function node in a previous
@@ -564,7 +563,7 @@
append(compiler.getCompileUnits().size()).
append(" compile unit(s)]");
- log.info(sb.toString());
+ log.fine(sb.toString());
}
return setStates(fn.setRootClass(null, rootClass), BYTECODE_INSTALLED);
--- a/nashorn/src/jdk/nashorn/internal/codegen/Compiler.java Tue Jul 22 11:55:03 2014 -0700
+++ b/nashorn/src/jdk/nashorn/internal/codegen/Compiler.java Tue Jul 29 14:21:45 2014 -0700
@@ -50,6 +50,7 @@
import java.util.concurrent.atomic.AtomicInteger;
import java.util.function.Consumer;
import java.util.logging.Level;
+
import jdk.internal.dynalink.support.NameCodec;
import jdk.nashorn.internal.codegen.ClassEmitter.Flag;
import jdk.nashorn.internal.codegen.types.Type;
@@ -502,7 +503,7 @@
*/
public FunctionNode compile(final FunctionNode functionNode, final CompilationPhases phases) throws CompilationException {
- log.info("Starting compile job for ", DebugLogger.quote(functionNode.getName()), " phases=", quote(phases.getDesc()));
+ log.finest("Starting compile job for ", DebugLogger.quote(functionNode.getName()), " phases=", quote(phases.getDesc()));
log.indent();
final String name = DebugLogger.quote(functionNode.getName());
@@ -531,7 +532,7 @@
time += (env.isTimingEnabled() ? phase.getEndTime() - phase.getStartTime() : 0L);
}
- if(typeInformationFile != null && !phases.isRestOfCompilation()) {
+ if (typeInformationFile != null && !phases.isRestOfCompilation()) {
OptimisticTypesPersistence.store(typeInformationFile, invalidatedProgramPoints);
}
--- a/nashorn/src/jdk/nashorn/internal/codegen/Lower.java Tue Jul 22 11:55:03 2014 -0700
+++ b/nashorn/src/jdk/nashorn/internal/codegen/Lower.java Tue Jul 29 14:21:45 2014 -0700
@@ -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;
--- a/nashorn/src/jdk/nashorn/internal/codegen/OptimisticTypesPersistence.java Tue Jul 22 11:55:03 2014 -0700
+++ b/nashorn/src/jdk/nashorn/internal/codegen/OptimisticTypesPersistence.java Tue Jul 29 14:21:45 2014 -0700
@@ -41,6 +41,7 @@
import java.util.Date;
import java.util.Map;
import java.util.TreeMap;
+
import jdk.nashorn.internal.codegen.types.Type;
import jdk.nashorn.internal.runtime.Context;
import jdk.nashorn.internal.runtime.RecompilableScriptFunctionData;
@@ -111,6 +112,7 @@
return;
}
final File file = ((LocationDescriptor)locationDescriptor).file;
+
AccessController.doPrivileged(new PrivilegedAction<Void>() {
@Override
public Void run() {
@@ -119,7 +121,7 @@
out.getChannel().lock(); // lock exclusive
final DataOutputStream dout = new DataOutputStream(new BufferedOutputStream(out));
dout.writeInt(optimisticTypes.size());
- for(Map.Entry<Integer, Type> e: optimisticTypes.entrySet()) {
+ for(final Map.Entry<Integer, Type> e: optimisticTypes.entrySet()) {
dout.writeInt(e.getKey());
final byte typeChar;
final Type type = e.getValue();
@@ -156,7 +158,6 @@
return null;
}
final File file = ((LocationDescriptor)locationDescriptor).file;
-
return AccessController.doPrivileged(new PrivilegedAction<Map<Integer, Type>>() {
@Override
public Map<Integer, Type> run() {
@@ -229,7 +230,7 @@
final String versionDirName;
try {
versionDirName = getVersionDirName();
- } catch(Exception e) {
+ } catch(final Exception e) {
getLogger().warning("Failed to calculate version dir name", e);
return null;
}
@@ -306,7 +307,7 @@
private static long getLastModifiedClassFile(final File dir, final long max) {
long currentMax = max;
- for(File f: dir.listFiles()) {
+ for(final File f: dir.listFiles()) {
if(f.getName().endsWith(".class")) {
final long lastModified = f.lastModified();
if(lastModified > currentMax) {
--- a/nashorn/src/jdk/nashorn/internal/ir/Block.java Tue Jul 22 11:55:03 2014 -0700
+++ b/nashorn/src/jdk/nashorn/internal/ir/Block.java Tue Jul 29 14:21:45 2014 -0700
@@ -149,7 +149,7 @@
@Override
public Node accept(final LexicalContext lc, final NodeVisitor<? extends LexicalContext> visitor) {
if (visitor.enterBlock(this)) {
- return visitor.leaveBlock(setStatements(lc, Node.accept(visitor, Statement.class, statements)));
+ return visitor.leaveBlock(setStatements(lc, Node.accept(visitor, statements)));
}
return this;
--- a/nashorn/src/jdk/nashorn/internal/ir/CallNode.java Tue Jul 22 11:55:03 2014 -0700
+++ b/nashorn/src/jdk/nashorn/internal/ir/CallNode.java Tue Jul 29 14:21:45 2014 -0700
@@ -30,6 +30,7 @@
import java.util.Collections;
import java.util.List;
import java.util.function.Function;
+
import jdk.nashorn.internal.codegen.types.Type;
import jdk.nashorn.internal.ir.annotations.Ignore;
import jdk.nashorn.internal.ir.annotations.Immutable;
@@ -175,10 +176,10 @@
if (visitor.enterCallNode(this)) {
final CallNode newCallNode = (CallNode)visitor.leaveCallNode(
setFunction((Expression)function.accept(visitor)).
- setArgs(Node.accept(visitor, Expression.class, args)).
+ setArgs(Node.accept(visitor, args)).
setEvalArgs(evalArgs == null ?
null :
- evalArgs.setArgs(Node.accept(visitor, Expression.class, evalArgs.getArgs()))));
+ evalArgs.setArgs(Node.accept(visitor, evalArgs.getArgs()))));
// Theoretically, we'd need to instead pass lc to every setter and do a replacement on each. In practice,
// setType from TypeOverride can't accept a lc, and we don't necessarily want to go there now.
if (this != newCallNode) {
--- a/nashorn/src/jdk/nashorn/internal/ir/FunctionNode.java Tue Jul 22 11:55:03 2014 -0700
+++ b/nashorn/src/jdk/nashorn/internal/ir/FunctionNode.java Tue Jul 29 14:21:45 2014 -0700
@@ -359,7 +359,7 @@
* @return a list of parameter nodes, potentially modified from original ones by the visitor.
*/
public List<IdentNode> visitParameters(final NodeVisitor<? extends LexicalContext> visitor) {
- return Node.accept(visitor, IdentNode.class, parameters);
+ return Node.accept(visitor, parameters);
}
/**
--- a/nashorn/src/jdk/nashorn/internal/ir/LexicalContext.java Tue Jul 22 11:55:03 2014 -0700
+++ b/nashorn/src/jdk/nashorn/internal/ir/LexicalContext.java Tue Jul 29 14:21:45 2014 -0700
@@ -27,6 +27,7 @@
import java.io.File;
import java.util.Iterator;
import java.util.NoSuchElementException;
+
import jdk.nashorn.internal.runtime.Debug;
import jdk.nashorn.internal.runtime.Source;
@@ -652,6 +653,7 @@
return lnext;
}
+ @SuppressWarnings("unchecked")
private T findNext() {
for (int i = index; i >= 0; i--) {
final Object node = stack[i];
@@ -660,7 +662,7 @@
}
if (clazz.isAssignableFrom(node.getClass())) {
index = i - 1;
- return clazz.cast(node);
+ return (T)node;
}
}
return null;
--- a/nashorn/src/jdk/nashorn/internal/ir/LiteralNode.java Tue Jul 22 11:55:03 2014 -0700
+++ b/nashorn/src/jdk/nashorn/internal/ir/LiteralNode.java Tue Jul 29 14:21:45 2014 -0700
@@ -934,7 +934,7 @@
public Node accept(final LexicalContext lc, final NodeVisitor<? extends LexicalContext> visitor) {
if (visitor.enterLiteralNode(this)) {
final List<Expression> oldValue = Arrays.asList(value);
- final List<Expression> newValue = Node.accept(visitor, Expression.class, oldValue);
+ final List<Expression> newValue = Node.accept(visitor, oldValue);
return visitor.leaveLiteralNode(oldValue != newValue ? setValue(lc, newValue) : this);
}
return this;
--- a/nashorn/src/jdk/nashorn/internal/ir/Node.java Tue Jul 22 11:55:03 2014 -0700
+++ b/nashorn/src/jdk/nashorn/internal/ir/Node.java Tue Jul 29 14:21:45 2014 -0700
@@ -27,6 +27,7 @@
import java.util.ArrayList;
import java.util.List;
+
import jdk.nashorn.internal.ir.visitor.NodeVisitor;
import jdk.nashorn.internal.parser.Token;
import jdk.nashorn.internal.parser.TokenType;
@@ -232,19 +233,34 @@
}
//on change, we have to replace the entire list, that's we can't simple do ListIterator.set
- static <T extends Node> List<T> accept(final NodeVisitor<? extends LexicalContext> visitor, final Class<T> clazz, final List<T> list) {
- boolean changed = false;
- final List<T> newList = new ArrayList<>();
-
- for (final Node node : list) {
- final T newNode = node == null ? null : clazz.cast(node.accept(visitor));
- if (newNode != node) {
- changed = true;
- }
- newList.add(newNode);
+ static <T extends Node> List<T> accept(final NodeVisitor<? extends LexicalContext> visitor, final List<T> list) {
+ final int size = list.size();
+ if (size == 0) {
+ return list;
}
- return changed ? newList : list;
+ List<T> newList = null;
+
+ for (int i = 0; i < size; i++) {
+ final T node = list.get(i);
+ @SuppressWarnings("unchecked")
+ final T newNode = node == null ? null : (T)node.accept(visitor);
+ if (newNode != node) {
+ if (newList == null) {
+ newList = new ArrayList<>(size);
+ for (int j = 0; j < i; j++) {
+ newList.add(list.get(j));
+ }
+ }
+ newList.add(newNode);
+ } else {
+ if (newList != null) {
+ newList.add(node);
+ }
+ }
+ }
+
+ return newList == null ? list : newList;
}
static <T extends LexicalContextNode> T replaceInLexicalContext(final LexicalContext lc, final T oldNode, final T newNode) {
--- a/nashorn/src/jdk/nashorn/internal/ir/ObjectNode.java Tue Jul 22 11:55:03 2014 -0700
+++ b/nashorn/src/jdk/nashorn/internal/ir/ObjectNode.java Tue Jul 29 14:21:45 2014 -0700
@@ -61,7 +61,7 @@
@Override
public Node accept(final NodeVisitor<? extends LexicalContext> visitor) {
if (visitor.enterObjectNode(this)) {
- return visitor.leaveObjectNode(setElements(Node.accept(visitor, PropertyNode.class, elements)));
+ return visitor.leaveObjectNode(setElements(Node.accept(visitor, elements)));
}
return this;
--- a/nashorn/src/jdk/nashorn/internal/ir/SwitchNode.java Tue Jul 22 11:55:03 2014 -0700
+++ b/nashorn/src/jdk/nashorn/internal/ir/SwitchNode.java Tue Jul 29 14:21:45 2014 -0700
@@ -104,7 +104,7 @@
if (visitor.enterSwitchNode(this)) {
return visitor.leaveSwitchNode(
setExpression(lc, (Expression)expression.accept(visitor)).
- setCases(lc, Node.accept(visitor, CaseNode.class, cases), defaultCaseIndex));
+ setCases(lc, Node.accept(visitor, cases), defaultCaseIndex));
}
return this;
--- a/nashorn/src/jdk/nashorn/internal/ir/TryNode.java Tue Jul 22 11:55:03 2014 -0700
+++ b/nashorn/src/jdk/nashorn/internal/ir/TryNode.java Tue Jul 29 14:21:45 2014 -0700
@@ -112,7 +112,7 @@
return visitor.leaveTryNode(
setBody(newBody).
setFinallyBody(newFinallyBody).
- setCatchBlocks(Node.accept(visitor, Block.class, catchBlocks)).
+ setCatchBlocks(Node.accept(visitor, catchBlocks)).
setFinallyCatchAll(finallyCatchAll));
}
--- a/nashorn/src/jdk/nashorn/internal/ir/debug/ClassHistogramElement.java Tue Jul 22 11:55:03 2014 -0700
+++ b/nashorn/src/jdk/nashorn/internal/ir/debug/ClassHistogramElement.java Tue Jul 29 14:21:45 2014 -0700
@@ -30,7 +30,7 @@
/**
* Class histogram element for IR / Java object instrumentation
*/
-public class ClassHistogramElement {
+public final class ClassHistogramElement {
/**
* Instance comparator
*/
--- a/nashorn/src/jdk/nashorn/internal/ir/debug/NashornTextifier.java Tue Jul 22 11:55:03 2014 -0700
+++ b/nashorn/src/jdk/nashorn/internal/ir/debug/NashornTextifier.java Tue Jul 29 14:21:45 2014 -0700
@@ -39,6 +39,7 @@
import java.util.List;
import java.util.Map;
import java.util.Set;
+
import jdk.internal.org.objectweb.asm.Attribute;
import jdk.internal.org.objectweb.asm.Handle;
import jdk.internal.org.objectweb.asm.Label;
@@ -1082,11 +1083,15 @@
contents.put(node, sb);
}
+ private static String dottyFriendly(final String name) {
+ return name.replace(':', '_');
+ }
+
@Override
public String toString() {
final StringBuilder sb = new StringBuilder();
- sb.append("digraph " + name + " {");
+ sb.append("digraph " + dottyFriendly(name) + " {");
sb.append("\n");
sb.append("\tgraph [fontname=courier]\n");
sb.append("\tnode [style=filled,color="+COLOR_DEFAULT+",fontname=courier]\n");
--- a/nashorn/src/jdk/nashorn/internal/ir/debug/ObjectSizeCalculator.java Tue Jul 22 11:55:03 2014 -0700
+++ b/nashorn/src/jdk/nashorn/internal/ir/debug/ObjectSizeCalculator.java Tue Jul 29 14:21:45 2014 -0700
@@ -52,7 +52,7 @@
* this fact and will report incorrect sizes, as it will presume the default JVM
* behavior.
*/
-public class ObjectSizeCalculator {
+public final class ObjectSizeCalculator {
/**
* Describes constant memory overheads for various constructs in a JVM implementation.
--- a/nashorn/src/jdk/nashorn/internal/lookup/MethodHandleFactory.java Tue Jul 22 11:55:03 2014 -0700
+++ b/nashorn/src/jdk/nashorn/internal/lookup/MethodHandleFactory.java Tue Jul 29 14:21:45 2014 -0700
@@ -124,11 +124,13 @@
* @return return value unmodified
*/
static Object traceReturn(final DebugLogger logger, final Object value) {
- final String str = " return" +
- (VOID_TAG.equals(value) ?
- ";" :
- " " + stripName(value) + "; // [type=" + (value == null ? "null]" : stripName(value.getClass()) + ']'));
- logger.log(TRACE_LEVEL, str);
+ if (logger.isEnabled()) {
+ final String str = " return" +
+ (VOID_TAG.equals(value) ?
+ ";" :
+ " " + stripName(value) + "; // [type=" + (value == null ? "null]" : stripName(value.getClass()) + ']'));
+ logger.log(TRACE_LEVEL, str);
+ }
return value;
}
--- a/nashorn/src/jdk/nashorn/internal/objects/Global.java Tue Jul 22 11:55:03 2014 -0700
+++ b/nashorn/src/jdk/nashorn/internal/objects/Global.java Tue Jul 29 14:21:45 2014 -0700
@@ -46,8 +46,10 @@
import java.util.concurrent.Callable;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.AtomicReference;
+
import javax.script.ScriptContext;
import javax.script.ScriptEngine;
+
import jdk.internal.dynalink.linker.GuardedInvocation;
import jdk.internal.dynalink.linker.LinkRequest;
import jdk.nashorn.api.scripting.ScriptObjectMirror;
@@ -563,6 +565,8 @@
* Initialize standard builtin objects like "Object", "Array", "Function" etc.
* as well as our extension builtin objects like "Java", "JSAdapter" as properties
* of the global scope object.
+ *
+ * @param engine ScriptEngine to initialize
*/
public void initBuiltinObjects(final ScriptEngine engine) {
if (this.builtinObject != null) {
@@ -1936,15 +1940,16 @@
}
private Object printImpl(final boolean newLine, final Object... objects) {
+ @SuppressWarnings("resource")
final PrintWriter out = scontext != null? new PrintWriter(scontext.getWriter()) : getContext().getEnv().getOut();
final StringBuilder sb = new StringBuilder();
- for (final Object object : objects) {
+ for (final Object obj : objects) {
if (sb.length() != 0) {
sb.append(' ');
}
- sb.append(JSType.toString(object));
+ sb.append(JSType.toString(obj));
}
// Print all at once to ensure thread friendly result.
--- a/nashorn/src/jdk/nashorn/internal/objects/NativeDate.java Tue Jul 22 11:55:03 2014 -0700
+++ b/nashorn/src/jdk/nashorn/internal/objects/NativeDate.java Tue Jul 29 14:21:45 2014 -0700
@@ -935,7 +935,6 @@
}
sb.append(' ');
- //$FALL-THROUGH$
case FORMAT_TIME:
final TimeZone tz = nd.getTimeZone();
final double utcTime = nd.getTime();
--- a/nashorn/src/jdk/nashorn/internal/objects/NativeObject.java Tue Jul 22 11:55:03 2014 -0700
+++ b/nashorn/src/jdk/nashorn/internal/objects/NativeObject.java Tue Jul 29 14:21:45 2014 -0700
@@ -39,6 +39,7 @@
import java.util.List;
import java.util.Set;
import java.util.concurrent.Callable;
+
import jdk.internal.dynalink.beans.BeansLinker;
import jdk.internal.dynalink.beans.StaticClass;
import jdk.internal.dynalink.linker.GuardedInvocation;
@@ -716,7 +717,7 @@
return target;
}
- /*
+ /**
* Binds the source mirror object's properties to the target object. Binding
* properties allows two-way read/write for the properties of the source object.
* All inherited, enumerable properties are also bound. This method is used to
@@ -731,7 +732,7 @@
// make accessor properties using dynamic invoker getters and setters
final AccessorProperty[] props = new AccessorProperty[keys.size()];
int idx = 0;
- for (String name : keys) {
+ for (final String name : keys) {
final MethodHandle getter = Bootstrap.createDynamicInvoker("dyn:getMethod|getProp|getElem:" + name, MIRROR_GETTER_TYPE);
final MethodHandle setter = Bootstrap.createDynamicInvoker("dyn:setProp|setElem:" + name, MIRROR_SETTER_TYPE);
props[idx] = AccessorProperty.create(name, 0, getter, setter);
--- a/nashorn/src/jdk/nashorn/internal/runtime/ECMAErrors.java Tue Jul 22 11:55:03 2014 -0700
+++ b/nashorn/src/jdk/nashorn/internal/runtime/ECMAErrors.java Tue Jul 29 14:21:45 2014 -0700
@@ -28,7 +28,7 @@
import java.text.MessageFormat;
import java.util.Locale;
import java.util.ResourceBundle;
-import jdk.nashorn.api.scripting.NashornException;
+
import jdk.nashorn.internal.codegen.CompilerConstants;
import jdk.nashorn.internal.objects.Global;
import jdk.nashorn.internal.scripts.JS;
--- a/nashorn/src/jdk/nashorn/internal/runtime/RecompilableScriptFunctionData.java Tue Jul 22 11:55:03 2014 -0700
+++ b/nashorn/src/jdk/nashorn/internal/runtime/RecompilableScriptFunctionData.java Tue Jul 29 14:21:45 2014 -0700
@@ -36,6 +36,7 @@
import java.util.Map;
import java.util.Set;
import java.util.TreeMap;
+
import jdk.internal.dynalink.support.NameCodec;
import jdk.nashorn.internal.codegen.CompileUnit;
import jdk.nashorn.internal.codegen.Compiler;
@@ -236,14 +237,14 @@
/**
* Initialize transient fields on deserialized instances
*
- * @param source source
- * @param installer code installer
+ * @param src source
+ * @param inst code installer
*/
- public void initTransients(final Source source, final CodeInstaller<ScriptEnvironment> installer) {
+ public void initTransients(final Source src, final CodeInstaller<ScriptEnvironment> inst) {
if (this.source == null && this.installer == null) {
- this.source = source;
- this.installer = installer;
- } else if (this.source != source || this.installer != installer) {
+ this.source = src;
+ this.installer = inst;
+ } else if (this.source != src || this.installer != inst) {
// Existing values must be same as those passed as parameters
throw new IllegalArgumentException();
}
--- a/nashorn/src/jdk/nashorn/internal/runtime/ScriptObject.java Tue Jul 22 11:55:03 2014 -0700
+++ b/nashorn/src/jdk/nashorn/internal/runtime/ScriptObject.java Tue Jul 29 14:21:45 2014 -0700
@@ -3626,7 +3626,6 @@
return MH.insertArguments(KNOWNFUNCPROPGUARDPROTO, 1, map, getter, depth, func);
}
- @SuppressWarnings("unused")
private static ScriptObject getProto(final ScriptObject self, final int depth) {
ScriptObject proto = self;
for (int d = 0; d < depth; d++) {
--- a/nashorn/src/jdk/nashorn/internal/runtime/ScriptRuntime.java Tue Jul 22 11:55:03 2014 -0700
+++ b/nashorn/src/jdk/nashorn/internal/runtime/ScriptRuntime.java Tue Jul 29 14:21:45 2014 -0700
@@ -484,17 +484,16 @@
final Object unwrapped = ScriptObjectMirror.unwrap(expression, global);
if (unwrapped instanceof ScriptObject) {
return new WithObject(scope, (ScriptObject)unwrapped);
- } else {
- // foreign ScriptObjectMirror
- ScriptObject exprObj = global.newObject();
- NativeObject.bindAllProperties(exprObj, (ScriptObjectMirror)expression);
- return new WithObject(scope, exprObj);
}
- } else {
- final Object wrappedExpr = JSType.toScriptObject(global, expression);
- if (wrappedExpr instanceof ScriptObject) {
- return new WithObject(scope, (ScriptObject)wrappedExpr);
- }
+ // foreign ScriptObjectMirror
+ final ScriptObject exprObj = global.newObject();
+ NativeObject.bindAllProperties(exprObj, (ScriptObjectMirror)expression);
+ return new WithObject(scope, exprObj);
+ }
+
+ final Object wrappedExpr = JSType.toScriptObject(global, expression);
+ if (wrappedExpr instanceof ScriptObject) {
+ return new WithObject(scope, (ScriptObject)wrappedExpr);
}
throw typeError(global, "cant.apply.with.to.non.scriptobject");
--- a/nashorn/src/jdk/nashorn/internal/runtime/WithObject.java Tue Jul 22 11:55:03 2014 -0700
+++ b/nashorn/src/jdk/nashorn/internal/runtime/WithObject.java Tue Jul 29 14:21:45 2014 -0700
@@ -31,12 +31,13 @@
import java.lang.invoke.MethodHandles;
import java.lang.invoke.MethodType;
import java.lang.invoke.SwitchPoint;
-import jdk.nashorn.api.scripting.AbstractJSObject;
-import jdk.nashorn.api.scripting.ScriptObjectMirror;
+
import jdk.internal.dynalink.CallSiteDescriptor;
import jdk.internal.dynalink.linker.GuardedInvocation;
import jdk.internal.dynalink.linker.LinkRequest;
import jdk.internal.dynalink.support.CallSiteDescriptorFactory;
+import jdk.nashorn.api.scripting.AbstractJSObject;
+import jdk.nashorn.api.scripting.ScriptObjectMirror;
import jdk.nashorn.internal.runtime.linker.NashornCallSiteDescriptor;
import jdk.nashorn.internal.runtime.linker.NashornGuards;
@@ -322,6 +323,7 @@
// We need to make sure correct 'this' is used for calls with Ident call
// expressions. We do so here using an AbstractJSObject instance.
return new AbstractJSObject() {
+ @Override
public Object call(final Object thiz, final Object... args) {
return mirror.call(withFilterExpression(receiver), args);
}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/nashorn/test/script/basic/compile-octane-normal.js Tue Jul 29 14:21:45 2014 -0700
@@ -0,0 +1,41 @@
+/*
+ * 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.
+ *
+ * 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.
+ */
+
+/**
+ * Make sure that we run with the class cache off to so that every
+ * run produces compile time and with optimistic type info caching
+ * and persistent code store off, for the same reasons. These last two
+ * are currently default, but this is not guaranteed to be the case
+ * forever, so make this test future safe, we specify them explicitly
+ *
+ * @test
+ * @runif external.octane
+ * @option -scripting
+ * @option -Dnashorn.typeInfo.disabled=true
+ * @option --class-cache-size=0
+ * @option --persistent-code-cache=false
+ */
+
+var fn = __DIR__ + 'compile-octane.js';
+var url = "file://" + fn;
+loadWithNewGlobal(new java.net.URL(url));
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/nashorn/test/script/basic/compile-octane-normal.js.EXPECTED Tue Jul 29 14:21:45 2014 -0700
@@ -0,0 +1,30 @@
+Compiling 'box2d'...
+Done.
+Compiling 'code-load'...
+Done.
+Compiling 'crypto'...
+Done.
+Compiling 'deltablue'...
+Done.
+Compiling 'earley-boyer'...
+Done.
+Compiling 'gbemu'... (2 files)
+Done.
+Compiling 'mandreel'...
+Done.
+Compiling 'navier-stokes'...
+Done.
+Compiling 'pdfjs'...
+Done.
+Compiling 'raytrace'...
+Done.
+Compiling 'regexp'...
+Done.
+Compiling 'richards'...
+Done.
+Compiling 'splay'...
+Done.
+Compiling 'typescript'... (3 files)
+Done.
+Compiling 'zlib'... (2 files)
+Done.
--- a/nashorn/test/script/basic/compile-octane-splitter.js Tue Jul 22 11:55:03 2014 -0700
+++ b/nashorn/test/script/basic/compile-octane-splitter.js Tue Jul 29 14:21:45 2014 -0700
@@ -22,12 +22,22 @@
*/
/**
+ * Make sure that we run with the class cache off to so that every
+ * run produces compile time and with optimistic type info caching
+ * and persistent code store off, for the same reasons. These last two
+ * are currently default, but this is not guaranteed to be the case
+ * forever, so make this test future safe, we specify them explicitly
+ *
* @test
* @option -Dnashorn.compiler.splitter.threshold=1000
* @fork
* @runif external.octane
* @option -scripting
+ * @option -Dnashorn.typeInfo.disabled=true
+ * @option --class-cache-size=0
+ * @option --persistent-code-cache=false
*/
-compile_only = true;
-load(__DIR__ + 'run-octane.js');
+var fn = __DIR__ + 'compile-octane.js';
+var url = "file://" + fn;
+loadWithNewGlobal(new java.net.URL(url));
--- a/nashorn/test/script/basic/compile-octane-splitter.js.EXPECTED Tue Jul 22 11:55:03 2014 -0700
+++ b/nashorn/test/script/basic/compile-octane-splitter.js.EXPECTED Tue Jul 29 14:21:45 2014 -0700
@@ -1,15 +1,30 @@
-[box2d] Compiled OK
-[code-load] Compiled OK
-[crypto] Compiled OK
-[deltablue] Compiled OK
-[earley-boyer] Compiled OK
-[gbemu] Compiled OK
-[mandreel] Compiled OK
-[navier-stokes] Compiled OK
-[pdfjs] Compiled OK
-[raytrace] Compiled OK
-[regexp] Compiled OK
-[richards] Compiled OK
-[splay] Compiled OK
-[typescript] Compiled OK
-[zlib] Compiled OK
+Compiling 'box2d'...
+Done.
+Compiling 'code-load'...
+Done.
+Compiling 'crypto'...
+Done.
+Compiling 'deltablue'...
+Done.
+Compiling 'earley-boyer'...
+Done.
+Compiling 'gbemu'... (2 files)
+Done.
+Compiling 'mandreel'...
+Done.
+Compiling 'navier-stokes'...
+Done.
+Compiling 'pdfjs'...
+Done.
+Compiling 'raytrace'...
+Done.
+Compiling 'regexp'...
+Done.
+Compiling 'richards'...
+Done.
+Compiling 'splay'...
+Done.
+Compiling 'typescript'... (3 files)
+Done.
+Compiling 'zlib'... (2 files)
+Done.
--- a/nashorn/test/script/basic/compile-octane.js Tue Jul 22 11:55:03 2014 -0700
+++ b/nashorn/test/script/basic/compile-octane.js Tue Jul 29 14:21:45 2014 -0700
@@ -22,10 +22,122 @@
*/
/**
- * @test
- * @runif external.octane
- * @option -scripting
+ * Make sure that we run with the class cache off to so that every
+ * run produces compile time and with optimistic type info caching
+ * and persistent code store off, for the same reasons. These last two
+ * are currently default, but this is not guaranteed to be the case
+ * forever, so make this test future safe, we specify them explicitly
+ *
+ * This means that if you use this subtest as a compilation test
+ * harness, pass the arguments:
+ *
+ * -scripting -Dnashorn.typeInfo.disabled=true --class-cache-size=0
+ * --persistent-code-cache=false
+ *
+ * @subtest
*/
-compile_only = true;
-load(__DIR__ + 'run-octane.js');
+load(__DIR__ + 'octane-payload.js');
+
+var DEFAULT_ITERS = 1; //default is one iteration through each benchmark
+var iters = DEFAULT_ITERS;
+var args = [];
+
+if (typeof $ARGS !== 'undefined') {
+ args = $ARGS;
+} else if (typeof arguments !== 'undefined' && arguments.length != 0) {
+ args = arguments;
+}
+
+var onlyTheseTests = [];
+var verbose = false;
+
+for (var i = 0; i < args.length; ) {
+ var arg = args[i];
+ if (arg === '--iterations') {
+ iters = +args[++i];
+ } else if (arg === '--verbose') {
+ verbose = true;
+ } else {
+ onlyTheseTests.push(arg);
+ }
+ i++;
+}
+
+if (isNaN(iters)) {
+ iters = DEFAULT_ITERS;
+}
+
+if (iters != DEFAULT_ITERS) {
+ print("Running " + iters + " iterations of each compilation.");
+}
+
+function print_if_verbose(x) {
+ if (verbose) {
+ print(x);
+ }
+}
+
+function contains(a, obj) {
+ for (var i = 0; i < a.length; i++) {
+ if (a[i] === obj) {
+ return true;
+ }
+ }
+ return false;
+}
+
+var testsCompiled = [];
+
+for (var j in tests) {
+ var test_name = tests[j].name;
+ var files = tests[j].files;
+
+ if (onlyTheseTests.length > 0 && !contains(onlyTheseTests, test_name)) {
+ print_if_verbose("Skipping " + test_name);
+ continue;
+ }
+
+ if (!contains(testsCompiled, test_name)) {
+ testsCompiled.push(test_name);
+ }
+
+ var str = "Compiling '" + test_name + "'...";
+ if (files.length > 1) {
+ str += " (" + files.length + " files)";
+ }
+ if (iters != 1) {
+ str += " (" + iters + " times)";
+ }
+ str + "...";
+ print(str);
+
+ for (var iteration = 0; iteration < iters; iteration++) {
+
+ //get a new global to avoid symbol pollution and reloads of base
+ //in the same namespace
+ var newGlobal = loadWithNewGlobal({script:'this', name:'test'});
+
+ //load base into the new global so we get BenchmarkSuite etc
+ newGlobal.load(base);
+
+ //load all files in the single benchmark
+ for (var k in files) {
+ var file = files[k];
+ if (iteration >= 0) { //only display message on first iteration
+ var str2 = "\t";
+ if (iters > 1) {
+ str2 += " [iteration " + (iteration + 1) + "]";
+ }
+ str2 += " processing file: " + file + "...";
+ print_if_verbose(str2);
+ }
+ newGlobal.load("file://" + path + file);
+ }
+ }
+ print("Done.");
+}
+
+if (testsCompiled.length == 0) {
+ print("Error: no tests given to compile");
+}
--- a/nashorn/test/script/basic/compile-octane.js.EXPECTED Tue Jul 22 11:55:03 2014 -0700
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,15 +0,0 @@
-[box2d] Compiled OK
-[code-load] Compiled OK
-[crypto] Compiled OK
-[deltablue] Compiled OK
-[earley-boyer] Compiled OK
-[gbemu] Compiled OK
-[mandreel] Compiled OK
-[navier-stokes] Compiled OK
-[pdfjs] Compiled OK
-[raytrace] Compiled OK
-[regexp] Compiled OK
-[richards] Compiled OK
-[splay] Compiled OK
-[typescript] Compiled OK
-[zlib] Compiled OK
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/nashorn/test/script/basic/octane-payload.js Tue Jul 29 14:21:45 2014 -0700
@@ -0,0 +1,58 @@
+/*
+ * 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.
+ *
+ * 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.
+ */
+
+/**
+ * @subtest
+ */
+
+function initZlib() {
+ zlib = new BenchmarkSuite('zlib', [152815148], [
+ new Benchmark('zlib', false, true, 10,
+ runZlib, undefined, tearDownZlib, null, 3)]);
+}
+
+var tests = [
+ {name:"box2d", files:["box2d.js"], suite:"Box2DBenchmark"},
+ {name:"code-load", files:["code-load.js"], suite:"CodeLoad"},
+ {name:"crypto", files:["crypto.js"], suite:"Crypto"},
+ {name:"deltablue", files:["deltablue.js"], suite:"DeltaBlue"},
+ {name:"earley-boyer", files:["earley-boyer.js"], suite:"EarleyBoyer"},
+ {name:"gbemu", files:["gbemu-part1.js", "gbemu-part2.js"], suite:"GameboyBenchmark"},
+ {name:"mandreel", files:["mandreel.js"], suite:"MandreelBenchmark"},
+ {name:"navier-stokes", files:["navier-stokes.js"], suite:"NavierStokes"},
+ {name:"pdfjs", files:["pdfjs.js"], suite:"PdfJS"},
+ {name:"raytrace", files:["raytrace.js"], suite:"RayTrace"},
+ {name:"regexp", files:["regexp.js"], suite:"RegExpSuite"},
+ {name:"richards", files:["richards.js"], suite:"Richards"},
+ {name:"splay", files:["splay.js"], suite:"Splay"},
+ {name:"typescript", files:["typescript.js", "typescript-input.js", "typescript-compiler.js"], suite:"typescript"},
+ //zlib currently disabled - requires read
+ {name:"zlib", files:["zlib.js", "zlib-data.js"], suite:"zlib", before:initZlib}
+];
+
+var dir = (typeof(__DIR__) == 'undefined') ? "test/script/basic/" : __DIR__;
+
+// TODO: why is this path hard coded when it's defined in project properties?
+var path = dir + "../external/octane/";
+var base = path + "base.js";
+
--- a/nashorn/test/script/basic/run-octane.js Tue Jul 22 11:55:03 2014 -0700
+++ b/nashorn/test/script/basic/run-octane.js Tue Jul 29 14:21:45 2014 -0700
@@ -24,36 +24,8 @@
/**
* @subtest
*/
-
-
-function initZlib() {
- zlib = new BenchmarkSuite('zlib', [152815148], [
- new Benchmark('zlib', false, true, 10,
- runZlib, undefined, tearDownZlib, null, 3)]);
-}
-
-var tests = [
- {name:"box2d", files:["box2d.js"], suite:"Box2DBenchmark"},
- {name:"code-load", files:["code-load.js"], suite:"CodeLoad"},
- {name:"crypto", files:["crypto.js"], suite:"Crypto"},
- {name:"deltablue", files:["deltablue.js"], suite:"DeltaBlue"},
- {name:"earley-boyer", files:["earley-boyer.js"], suite:"EarleyBoyer"},
- {name:"gbemu", files:["gbemu-part1.js", "gbemu-part2.js"], suite:"GameboyBenchmark"},
- {name:"mandreel", files:["mandreel.js"], suite:"MandreelBenchmark"},
- {name:"navier-stokes", files:["navier-stokes.js"], suite:"NavierStokes"},
- {name:"pdfjs", files:["pdfjs.js"], suite:"PdfJS"},
- {name:"raytrace", files:["raytrace.js"], suite:"RayTrace"},
- {name:"regexp", files:["regexp.js"], suite:"RegExpSuite"},
- {name:"richards", files:["richards.js"], suite:"Richards"},
- {name:"splay", files:["splay.js"], suite:"Splay"},
- {name:"typescript", files:["typescript.js", "typescript-input.js", "typescript-compiler.js"], suite:"typescript"},
- //zlib currently disabled - requires read
- {name:"zlib", files:["zlib.js", "zlib-data.js"], suite:"zlib", before:initZlib}
-];
-var dir = (typeof(__DIR__) == 'undefined') ? "test/script/basic/" : __DIR__;
-
-// TODO: why is this path hard coded when it's defined in project properties?
-var path = dir + "../external/octane/";
+var payload = __DIR__ + "octane-payload.js";
+load(payload);
var runtime = undefined;
var verbose = false;