8013203: A collection of smaller speedups to compilation pipeline

Reviewed-by: hannesw, jlaskey
This commit is contained in:
Attila Szegedi 2013-04-25 14:47:17 +02:00
parent 1ac0e870a1
commit d32994d944
6 changed files with 95 additions and 51 deletions

View File

@ -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;

View File

@ -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;

View File

@ -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);
}

View File

@ -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.
*

View File

@ -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;
}
}

View File

@ -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));
}
}