8048869: Reduce compile time by about 5% by removing the Class.casts from the AST nodes
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
This commit is contained in:
parent
ad9ca4fb43
commit
5c93b19922
nashorn
src/jdk
internal/dynalink/support
nashorn
api/scripting
internal
codegen
ir
Block.javaCallNode.javaFunctionNode.javaLexicalContext.javaLiteralNode.javaNode.javaObjectNode.javaSwitchNode.javaTryNode.java
debug
lookup
objects
runtime
test/script/basic
@ -111,7 +111,7 @@ public class CompositeTypeBasedGuardingDynamicLinker implements TypeBasedGuardin
|
||||
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 @@ public class CompositeTypeBasedGuardingDynamicLinker implements TypeBasedGuardin
|
||||
case 1: {
|
||||
list = new LinkedList<>(list);
|
||||
}
|
||||
//$FALL-THROUGH$
|
||||
default: {
|
||||
list.add(linker);
|
||||
}
|
||||
|
@ -40,6 +40,7 @@ import java.security.ProtectionDomain;
|
||||
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.ScriptEngine;
|
||||
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 @@ public final class NashornScriptEngine extends AbstractScriptEngine implements C
|
||||
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 @@ public final class NashornScriptEngine extends AbstractScriptEngine implements C
|
||||
}
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
@ -1097,7 +1097,11 @@ final class CodeGenerator extends NodeOperatorVisitor<CodeGeneratorLexicalContex
|
||||
|
||||
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;
|
||||
}
|
||||
|
@ -43,7 +43,6 @@ import java.io.PrintWriter;
|
||||
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 @@ enum CompilationPhase {
|
||||
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 @@ enum CompilationPhase {
|
||||
append(compiler.getCompileUnits().size()).
|
||||
append(" compile unit(s)]");
|
||||
|
||||
log.info(sb.toString());
|
||||
log.fine(sb.toString());
|
||||
}
|
||||
|
||||
return setStates(fn.setRootClass(null, rootClass), BYTECODE_INSTALLED);
|
||||
|
@ -50,6 +50,7 @@ import java.util.TreeMap;
|
||||
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 final class Compiler implements Loggable {
|
||||
*/
|
||||
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 @@ public final class Compiler implements Loggable {
|
||||
time += (env.isTimingEnabled() ? phase.getEndTime() - phase.getStartTime() : 0L);
|
||||
}
|
||||
|
||||
if(typeInformationFile != null && !phases.isRestOfCompilation()) {
|
||||
if (typeInformationFile != null && !phases.isRestOfCompilation()) {
|
||||
OptimisticTypesPersistence.store(typeInformationFile, invalidatedProgramPoints);
|
||||
}
|
||||
|
||||
|
@ -34,6 +34,7 @@ import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.ListIterator;
|
||||
|
||||
import jdk.nashorn.internal.ir.BaseNode;
|
||||
import jdk.nashorn.internal.ir.BinaryNode;
|
||||
import jdk.nashorn.internal.ir.Block;
|
||||
|
@ -41,6 +41,7 @@ import java.util.Base64;
|
||||
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 @@ public final class OptimisticTypesPersistence {
|
||||
return;
|
||||
}
|
||||
final File file = ((LocationDescriptor)locationDescriptor).file;
|
||||
|
||||
AccessController.doPrivileged(new PrivilegedAction<Void>() {
|
||||
@Override
|
||||
public Void run() {
|
||||
@ -119,7 +121,7 @@ public final class OptimisticTypesPersistence {
|
||||
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 @@ public final class OptimisticTypesPersistence {
|
||||
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 @@ public final class OptimisticTypesPersistence {
|
||||
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 @@ public final class OptimisticTypesPersistence {
|
||||
|
||||
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) {
|
||||
|
@ -149,7 +149,7 @@ public class Block extends Node implements BreakableNode, Terminal, Flags<Block>
|
||||
@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;
|
||||
|
@ -30,6 +30,7 @@ import static jdk.nashorn.internal.runtime.UnwarrantedOptimismException.INVALID_
|
||||
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 @@ public final class CallNode extends LexicalContextExpression implements Optimist
|
||||
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) {
|
||||
|
@ -359,7 +359,7 @@ public final class FunctionNode extends LexicalContextExpression implements Flag
|
||||
* @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);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -27,6 +27,7 @@ package jdk.nashorn.internal.ir;
|
||||
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 @@ public class LexicalContext {
|
||||
return lnext;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private T findNext() {
|
||||
for (int i = index; i >= 0; i--) {
|
||||
final Object node = stack[i];
|
||||
@ -660,7 +662,7 @@ public class LexicalContext {
|
||||
}
|
||||
if (clazz.isAssignableFrom(node.getClass())) {
|
||||
index = i - 1;
|
||||
return clazz.cast(node);
|
||||
return (T)node;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
|
@ -934,7 +934,7 @@ public abstract class LiteralNode<T> extends Expression implements PropertyKey {
|
||||
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;
|
||||
|
@ -27,6 +27,7 @@ package jdk.nashorn.internal.ir;
|
||||
|
||||
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 @@ public abstract class Node implements Cloneable {
|
||||
}
|
||||
|
||||
//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) {
|
||||
|
@ -61,7 +61,7 @@ public final class ObjectNode extends Expression {
|
||||
@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;
|
||||
|
@ -104,7 +104,7 @@ public final class SwitchNode extends BreakableStatement {
|
||||
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;
|
||||
|
@ -112,7 +112,7 @@ public final class TryNode extends Statement implements JoinPredecessor {
|
||||
return visitor.leaveTryNode(
|
||||
setBody(newBody).
|
||||
setFinallyBody(newFinallyBody).
|
||||
setCatchBlocks(Node.accept(visitor, Block.class, catchBlocks)).
|
||||
setCatchBlocks(Node.accept(visitor, catchBlocks)).
|
||||
setFinallyCatchAll(finallyCatchAll));
|
||||
}
|
||||
|
||||
|
@ -30,7 +30,7 @@ import java.util.Comparator;
|
||||
/**
|
||||
* Class histogram element for IR / Java object instrumentation
|
||||
*/
|
||||
public class ClassHistogramElement {
|
||||
public final class ClassHistogramElement {
|
||||
/**
|
||||
* Instance comparator
|
||||
*/
|
||||
|
@ -39,6 +39,7 @@ import java.util.LinkedHashSet;
|
||||
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 @@ public final class NashornTextifier extends Printer {
|
||||
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");
|
||||
|
@ -52,7 +52,7 @@ import java.util.Map;
|
||||
* 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.
|
||||
|
@ -124,11 +124,13 @@ public final class MethodHandleFactory {
|
||||
* @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;
|
||||
}
|
||||
|
||||
|
@ -46,8 +46,10 @@ import java.util.Map;
|
||||
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 @@ public final class Global extends ScriptObject implements Scope {
|
||||
* 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 @@ public final class Global extends ScriptObject implements Scope {
|
||||
}
|
||||
|
||||
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.
|
||||
|
@ -935,7 +935,6 @@ public final class NativeDate extends ScriptObject {
|
||||
}
|
||||
sb.append(' ');
|
||||
|
||||
//$FALL-THROUGH$
|
||||
case FORMAT_TIME:
|
||||
final TimeZone tz = nd.getTimeZone();
|
||||
final double utcTime = nd.getTime();
|
||||
|
@ -39,6 +39,7 @@ import java.util.HashSet;
|
||||
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 @@ public final class NativeObject {
|
||||
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 @@ public final class NativeObject {
|
||||
// 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);
|
||||
|
@ -28,7 +28,7 @@ package jdk.nashorn.internal.runtime;
|
||||
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;
|
||||
|
@ -36,6 +36,7 @@ import java.util.HashSet;
|
||||
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 @@ public final class RecompilableScriptFunctionData extends ScriptFunctionData imp
|
||||
/**
|
||||
* 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();
|
||||
}
|
||||
|
@ -3626,7 +3626,6 @@ public abstract class ScriptObject implements PropertyAccess {
|
||||
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++) {
|
||||
|
@ -484,17 +484,16 @@ public final class ScriptRuntime {
|
||||
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");
|
||||
|
@ -31,12 +31,13 @@ import java.lang.invoke.MethodHandle;
|
||||
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 @@ public final class WithObject extends ScriptObject implements Scope {
|
||||
// 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);
|
||||
}
|
||||
|
41
nashorn/test/script/basic/compile-octane-normal.js
Normal file
41
nashorn/test/script/basic/compile-octane-normal.js
Normal file
@ -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));
|
30
nashorn/test/script/basic/compile-octane-normal.js.EXPECTED
Normal file
30
nashorn/test/script/basic/compile-octane-normal.js.EXPECTED
Normal file
@ -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.
|
@ -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));
|
||||
|
@ -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.
|
||||
|
@ -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");
|
||||
}
|
||||
|
@ -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
|
58
nashorn/test/script/basic/octane-payload.js
Normal file
58
nashorn/test/script/basic/octane-payload.js
Normal file
@ -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";
|
||||
|
@ -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;
|
||||
|
Loading…
x
Reference in New Issue
Block a user