mirror of
https://github.com/openjdk/jdk.git
synced 2026-04-21 04:10:33 +00:00
8013203: A collection of smaller speedups to compilation pipeline
Reviewed-by: hannesw, jlaskey
This commit is contained in:
parent
1ac0e870a1
commit
d32994d944
@ -1120,7 +1120,7 @@ final class CodeGenerator extends NodeOperatorVisitor {
|
||||
|
||||
@Override
|
||||
public boolean enterLineNumberNode(final LineNumberNode lineNumberNode) {
|
||||
final Label label = new Label("line:" + lineNumberNode.getLineNumber() + " (" + getLexicalContext().getCurrentFunction().getName() + ")");
|
||||
final Label label = new Label((String)null);
|
||||
method.label(label);
|
||||
method.lineNumber(lineNumberNode.getLineNumber(), label);
|
||||
return false;
|
||||
|
||||
@ -32,7 +32,6 @@ import java.util.ArrayList;
|
||||
import java.util.HashSet;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
|
||||
import jdk.nashorn.internal.codegen.types.Type;
|
||||
import jdk.nashorn.internal.ir.AccessNode;
|
||||
import jdk.nashorn.internal.ir.Assignment;
|
||||
|
||||
@ -71,7 +71,6 @@ import java.util.ArrayDeque;
|
||||
import java.util.EnumSet;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
|
||||
import jdk.internal.dynalink.support.NameCodec;
|
||||
import jdk.internal.org.objectweb.asm.Handle;
|
||||
import jdk.internal.org.objectweb.asm.MethodVisitor;
|
||||
@ -674,7 +673,7 @@ public class MethodEmitter implements Emitter {
|
||||
* @return the method emitter
|
||||
*/
|
||||
MethodEmitter loadUndefined(final Type type) {
|
||||
debug("load undefined " + type);
|
||||
debug("load undefined ", type);
|
||||
pushType(type.loadUndefined(method));
|
||||
return this;
|
||||
}
|
||||
@ -686,7 +685,7 @@ public class MethodEmitter implements Emitter {
|
||||
* @return the method emitter
|
||||
*/
|
||||
MethodEmitter loadEmpty(final Type type) {
|
||||
debug("load empty " + type);
|
||||
debug("load empty ", type);
|
||||
pushType(type.loadEmpty(method));
|
||||
return this;
|
||||
}
|
||||
@ -1076,7 +1075,7 @@ public class MethodEmitter implements Emitter {
|
||||
* @return the method emitter
|
||||
*/
|
||||
MethodEmitter newarray(final ArrayType arrayType) {
|
||||
debug("newarray ", "arrayType=" + arrayType);
|
||||
debug("newarray ", "arrayType=", arrayType);
|
||||
popType(Type.INT); //LENGTH
|
||||
pushType(arrayType.newarray(method));
|
||||
return this;
|
||||
@ -1155,7 +1154,7 @@ public class MethodEmitter implements Emitter {
|
||||
* @return the method emitter
|
||||
*/
|
||||
MethodEmitter invokespecial(final String className, final String methodName, final String methodDescriptor) {
|
||||
debug("invokespecial", className + "." + methodName + methodDescriptor);
|
||||
debug("invokespecial", className, ".", methodName, methodDescriptor);
|
||||
return invoke(INVOKESPECIAL, className, methodName, methodDescriptor, true);
|
||||
}
|
||||
|
||||
@ -1169,7 +1168,7 @@ public class MethodEmitter implements Emitter {
|
||||
* @return the method emitter
|
||||
*/
|
||||
MethodEmitter invokevirtual(final String className, final String methodName, final String methodDescriptor) {
|
||||
debug("invokevirtual", className + "." + methodName + methodDescriptor + " " + stack);
|
||||
debug("invokevirtual", className, ".", methodName, methodDescriptor, " ", stack);
|
||||
return invoke(INVOKEVIRTUAL, className, methodName, methodDescriptor, true);
|
||||
}
|
||||
|
||||
@ -1183,7 +1182,7 @@ public class MethodEmitter implements Emitter {
|
||||
* @return the method emitter
|
||||
*/
|
||||
MethodEmitter invokestatic(final String className, final String methodName, final String methodDescriptor) {
|
||||
debug("invokestatic", className + "." + methodName + methodDescriptor);
|
||||
debug("invokestatic", className, ".", methodName, methodDescriptor);
|
||||
invoke(INVOKESTATIC, className, methodName, methodDescriptor, false);
|
||||
return this;
|
||||
}
|
||||
@ -1216,7 +1215,7 @@ public class MethodEmitter implements Emitter {
|
||||
* @return the method emitter
|
||||
*/
|
||||
MethodEmitter invokeinterface(final String className, final String methodName, final String methodDescriptor) {
|
||||
debug("invokeinterface", className + "." + methodName + methodDescriptor);
|
||||
debug("invokeinterface", className, ".", methodName, methodDescriptor);
|
||||
return invoke(INVOKEINTERFACE, className, methodName, methodDescriptor, true);
|
||||
}
|
||||
|
||||
@ -1268,11 +1267,11 @@ public class MethodEmitter implements Emitter {
|
||||
*/
|
||||
void conditionalJump(final Condition cond, final boolean isCmpG, final Label trueLabel) {
|
||||
if (peekType().isCategory2()) {
|
||||
debug("[ld]cmp isCmpG=" + isCmpG);
|
||||
debug("[ld]cmp isCmpG=", isCmpG);
|
||||
pushType(get2n().cmp(method, isCmpG));
|
||||
jump(Condition.toUnary(cond), trueLabel, 1);
|
||||
} else {
|
||||
debug("if" + cond);
|
||||
debug("if", cond);
|
||||
jump(Condition.toBinary(cond, peekType().isObject()), trueLabel, 2);
|
||||
}
|
||||
}
|
||||
@ -1517,7 +1516,7 @@ public class MethodEmitter implements Emitter {
|
||||
*/
|
||||
private void mergeStackTo(final Label label) {
|
||||
final ArrayDeque<Type> labelStack = label.getStack();
|
||||
//debug(labelStack == null ? " >> Control flow - first visit " + label : " >> Control flow - JOIN with " + labelStack + " at " + label);
|
||||
//debug(labelStack == null ? " >> Control flow - first visit ", label : " >> Control flow - JOIN with ", labelStack, " at ", label);
|
||||
if (labelStack == null) {
|
||||
assert stack != null;
|
||||
label.setStack(stack.clone());
|
||||
@ -1710,7 +1709,7 @@ public class MethodEmitter implements Emitter {
|
||||
* @return the method emitter
|
||||
*/
|
||||
MethodEmitter dynamicNew(final int argCount, final int flags) {
|
||||
debug("dynamic_new", "argcount=" + argCount);
|
||||
debug("dynamic_new", "argcount=", argCount);
|
||||
final String signature = getDynamicSignature(Type.OBJECT, argCount);
|
||||
method.visitInvokeDynamicInsn("dyn:new", signature, LINKERBOOTSTRAP, flags);
|
||||
pushType(Type.OBJECT); //TODO fix result type
|
||||
@ -1727,7 +1726,7 @@ public class MethodEmitter implements Emitter {
|
||||
* @return the method emitter
|
||||
*/
|
||||
MethodEmitter dynamicCall(final Type returnType, final int argCount, final int flags) {
|
||||
debug("dynamic_call", "args=" + argCount, "returnType=" + returnType);
|
||||
debug("dynamic_call", "args=", argCount, "returnType=", returnType);
|
||||
final String signature = getDynamicSignature(returnType, argCount); // +1 because the function itself is the 1st parameter for dynamic calls (what you call - call target)
|
||||
debug(" signature", signature);
|
||||
method.visitInvokeDynamicInsn("dyn:call", signature, LINKERBOOTSTRAP, flags);
|
||||
@ -1746,7 +1745,7 @@ public class MethodEmitter implements Emitter {
|
||||
* @return the method emitter
|
||||
*/
|
||||
MethodEmitter dynamicRuntimeCall(final String name, final Type returnType, final RuntimeNode.Request request) {
|
||||
debug("dynamic_runtime_call", name, "args=" + request.getArity(), "returnType=" + returnType);
|
||||
debug("dynamic_runtime_call", name, "args=", request.getArity(), "returnType=", returnType);
|
||||
final String signature = getDynamicSignature(returnType, request.getArity());
|
||||
debug(" signature", signature);
|
||||
method.visitInvokeDynamicInsn(name, signature, RUNTIMEBOOTSTRAP);
|
||||
@ -1817,7 +1816,7 @@ public class MethodEmitter implements Emitter {
|
||||
* @return the method emitter
|
||||
*/
|
||||
MethodEmitter dynamicGetIndex(final Type result, final int flags, final boolean isMethod) {
|
||||
debug("dynamic_get_index", peekType(1) + "[" + peekType() + "]");
|
||||
debug("dynamic_get_index", peekType(1), "[", peekType(), "]");
|
||||
|
||||
Type resultType = result;
|
||||
if (result.isBoolean()) {
|
||||
@ -1853,7 +1852,7 @@ public class MethodEmitter implements Emitter {
|
||||
* @param flags call site flags for setter
|
||||
*/
|
||||
void dynamicSetIndex(final int flags) {
|
||||
debug("dynamic_set_index", peekType(2) + "[" + peekType(1) + "] =", peekType());
|
||||
debug("dynamic_set_index", peekType(2), "[", peekType(1), "] =", peekType());
|
||||
|
||||
Type value = peekType();
|
||||
if (value.isObject() || value.isBoolean()) {
|
||||
@ -1953,7 +1952,7 @@ public class MethodEmitter implements Emitter {
|
||||
* @return the method emitter
|
||||
*/
|
||||
MethodEmitter getField(final String className, final String fieldName, final String fieldDescriptor) {
|
||||
debug("getfield", "receiver=" + peekType(), className + "." + fieldName + fieldDescriptor);
|
||||
debug("getfield", "receiver=", peekType(), className, ".", fieldName, fieldDescriptor);
|
||||
final Type receiver = popType();
|
||||
assert receiver.isObject();
|
||||
method.visitFieldInsn(GETFIELD, className, fieldName, fieldDescriptor);
|
||||
@ -1971,7 +1970,7 @@ public class MethodEmitter implements Emitter {
|
||||
* @return the method emitter
|
||||
*/
|
||||
MethodEmitter getStatic(final String className, final String fieldName, final String fieldDescriptor) {
|
||||
debug("getstatic", className + "." + fieldName + "." + fieldDescriptor);
|
||||
debug("getstatic", className, ".", fieldName, ".", fieldDescriptor);
|
||||
method.visitFieldInsn(GETSTATIC, className, fieldName, fieldDescriptor);
|
||||
pushType(fieldType(fieldDescriptor));
|
||||
return this;
|
||||
@ -1985,7 +1984,7 @@ public class MethodEmitter implements Emitter {
|
||||
* @param fieldDescriptor field descriptor
|
||||
*/
|
||||
void putField(final String className, final String fieldName, final String fieldDescriptor) {
|
||||
debug("putfield", "receiver=" + peekType(1), "value=" + peekType());
|
||||
debug("putfield", "receiver=", peekType(1), "value=", peekType());
|
||||
popType(fieldType(fieldDescriptor));
|
||||
popType(Type.OBJECT);
|
||||
method.visitFieldInsn(PUTFIELD, className, fieldName, fieldDescriptor);
|
||||
@ -1999,7 +1998,7 @@ public class MethodEmitter implements Emitter {
|
||||
* @param fieldDescriptor field descriptor
|
||||
*/
|
||||
void putStatic(final String className, final String fieldName, final String fieldDescriptor) {
|
||||
debug("putfield", "value=" + peekType());
|
||||
debug("putfield", "value=", peekType());
|
||||
popType(fieldType(fieldDescriptor));
|
||||
method.visitFieldInsn(PUTSTATIC, className, fieldName, fieldDescriptor);
|
||||
}
|
||||
|
||||
@ -221,6 +221,22 @@ public final class ObjectClassGenerator {
|
||||
return SCRIPTS_PACKAGE + '/' + JS_OBJECT_PREFIX.symbolName() + fieldCount + SCOPE_MARKER + paramCount;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the number of fields in the JavaScript scope class. Its name had to be generated using either
|
||||
* {@link #getClassName(int)} or {@link #getClassName(int, int)}.
|
||||
* @param clazz the JavaScript scope class.
|
||||
* @return the number of fields in the scope class.
|
||||
*/
|
||||
public static int getFieldCount(Class<?> clazz) {
|
||||
final String name = clazz.getSimpleName();
|
||||
final String prefix = JS_OBJECT_PREFIX.symbolName();
|
||||
if(prefix.equals(name)) {
|
||||
return 0;
|
||||
}
|
||||
final int scopeMarker = name.indexOf(SCOPE_MARKER);
|
||||
return Integer.parseInt(scopeMarker == -1 ? name.substring(prefix.length()) : name.substring(prefix.length(), scopeMarker));
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the name of a field based on number and type.
|
||||
*
|
||||
|
||||
@ -57,6 +57,9 @@ import jdk.nashorn.internal.runtime.options.Options;
|
||||
*/
|
||||
@SuppressWarnings("fallthrough")
|
||||
public class Lexer extends Scanner {
|
||||
private static final long MIN_INT_L = Integer.MIN_VALUE;
|
||||
private static final long MAX_INT_L = Integer.MAX_VALUE;
|
||||
|
||||
private static final boolean XML_LITERALS = Options.getBooleanProperty("nashorn.lexer.xmlliterals");
|
||||
|
||||
/** Content source. */
|
||||
@ -984,27 +987,27 @@ public class Lexer extends Scanner {
|
||||
*/
|
||||
private static Number valueOf(final String valueString, final int radix) throws NumberFormatException {
|
||||
try {
|
||||
return Integer.valueOf(valueString, radix);
|
||||
} catch (final NumberFormatException e) {
|
||||
try {
|
||||
return Long.valueOf(valueString, radix);
|
||||
} catch (final NumberFormatException e2) {
|
||||
if (radix == 10) {
|
||||
return Double.valueOf(valueString);
|
||||
}
|
||||
|
||||
double value = 0.0;
|
||||
|
||||
for (int i = 0; i < valueString.length(); i++) {
|
||||
final char ch = valueString.charAt(i);
|
||||
// Preverified, should always be a valid digit.
|
||||
final int digit = convertDigit(ch, radix);
|
||||
value *= radix;
|
||||
value += digit;
|
||||
}
|
||||
|
||||
return value;
|
||||
final long value = Long.parseLong(valueString, radix);
|
||||
if(value >= MIN_INT_L && value <= MAX_INT_L) {
|
||||
return Integer.valueOf((int)value);
|
||||
}
|
||||
return Long.valueOf(value);
|
||||
} catch (final NumberFormatException e) {
|
||||
if (radix == 10) {
|
||||
return Double.valueOf(valueString);
|
||||
}
|
||||
|
||||
double value = 0.0;
|
||||
|
||||
for (int i = 0; i < valueString.length(); i++) {
|
||||
final char ch = valueString.charAt(i);
|
||||
// Preverified, should always be a valid digit.
|
||||
final int digit = convertDigit(ch, radix);
|
||||
value *= radix;
|
||||
value += digit;
|
||||
}
|
||||
|
||||
return value;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -54,10 +54,24 @@ import jdk.nashorn.internal.lookup.MethodHandleFactory;
|
||||
* @see SpillProperty
|
||||
*/
|
||||
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 int NOOF_TYPES = getNumberOfAccessorTypes();
|
||||
|
||||
/**
|
||||
* 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
|
||||
* these are the most frequently retrieved ones, and lookup of method handle natives only registers in the profiler
|
||||
* for them.
|
||||
*/
|
||||
private static ClassValue<GettersSetters> GETTERS_SETTERS = new ClassValue<GettersSetters>() {
|
||||
@Override
|
||||
protected GettersSetters computeValue(Class<?> structure) {
|
||||
return new GettersSetters(structure);
|
||||
}
|
||||
};
|
||||
|
||||
/** Property getter cache */
|
||||
private MethodHandle[] getters = new MethodHandle[NOOF_TYPES];
|
||||
|
||||
@ -152,6 +166,22 @@ public class AccessorProperty extends Property {
|
||||
setCurrentType(getterType);
|
||||
}
|
||||
|
||||
private static class GettersSetters {
|
||||
final MethodHandle[] getters;
|
||||
final MethodHandle[] setters;
|
||||
|
||||
public GettersSetters(Class<?> structure) {
|
||||
final int fieldCount = ObjectClassGenerator.getFieldCount(structure);
|
||||
getters = new MethodHandle[fieldCount];
|
||||
setters = new MethodHandle[fieldCount];
|
||||
for(int i = 0; i < fieldCount; ++i) {
|
||||
final String fieldName = ObjectClassGenerator.getFieldName(i, Type.OBJECT);
|
||||
getters[i] = MH.getter(lookup, structure, fieldName, Type.OBJECT.getTypeClass());
|
||||
setters[i] = MH.setter(lookup, structure, fieldName, Type.OBJECT.getTypeClass());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructor for dual field AccessorPropertys.
|
||||
*
|
||||
@ -171,22 +201,19 @@ public class AccessorProperty extends Property {
|
||||
primitiveGetter = null;
|
||||
primitiveSetter = null;
|
||||
|
||||
final MethodHandles.Lookup lookup = MethodHandles.lookup();
|
||||
|
||||
if (isParameter() && hasArguments()) {
|
||||
final MethodHandle arguments = MH.getter(MethodHandles.lookup(), structure, "arguments", Object.class);
|
||||
final MethodHandle arguments = MH.getter(lookup, structure, "arguments", Object.class);
|
||||
final MethodHandle argumentsSO = MH.asType(arguments, arguments.type().changeReturnType(ScriptObject.class));
|
||||
|
||||
objectGetter = MH.insertArguments(MH.filterArguments(ScriptObject.GET_ARGUMENT.methodHandle(), 0, argumentsSO), 1, slot);
|
||||
objectSetter = MH.insertArguments(MH.filterArguments(ScriptObject.SET_ARGUMENT.methodHandle(), 0, argumentsSO), 1, slot);
|
||||
} else {
|
||||
final String fieldNameObject = ObjectClassGenerator.getFieldName(slot, Type.OBJECT);
|
||||
final String fieldNamePrimitive = ObjectClassGenerator.getFieldName(slot, ObjectClassGenerator.PRIMITIVE_TYPE);
|
||||
|
||||
objectGetter = MH.getter(lookup, structure, fieldNameObject, Type.OBJECT.getTypeClass());
|
||||
objectSetter = MH.setter(lookup, structure, fieldNameObject, Type.OBJECT.getTypeClass());
|
||||
final GettersSetters gs = GETTERS_SETTERS.get(structure);
|
||||
objectGetter = gs.getters[slot];
|
||||
objectSetter = gs.setters[slot];
|
||||
|
||||
if (!OBJECT_FIELDS_ONLY) {
|
||||
final String fieldNamePrimitive = ObjectClassGenerator.getFieldName(slot, ObjectClassGenerator.PRIMITIVE_TYPE);
|
||||
primitiveGetter = MH.getter(lookup, structure, fieldNamePrimitive, PRIMITIVE_TYPE.getTypeClass());
|
||||
primitiveSetter = MH.setter(lookup, structure, fieldNamePrimitive, PRIMITIVE_TYPE.getTypeClass());
|
||||
}
|
||||
@ -365,7 +392,7 @@ public class AccessorProperty extends Property {
|
||||
}
|
||||
|
||||
private static MethodHandle findOwnMH(final String name, final Class<?> rtype, final Class<?>... types) {
|
||||
return MH.findStatic(MethodHandles.lookup(), AccessorProperty.class, name, MH.type(rtype, types));
|
||||
return MH.findStatic(lookup, AccessorProperty.class, name, MH.type(rtype, types));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user