Mercurial > hg > graal-compiler
changeset 5811:6a725f3c4bb0
Merge
author | Gilles Duboscq <duboscq@ssw.jku.at> |
---|---|
date | Mon, 09 Jul 2012 14:22:22 +0200 |
parents | 506e76281145 (diff) bc237d8b6f99 (current diff) |
children | 32613b375b30 |
files | graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/GraalOptions.java graal/com.oracle.graal.lir/src/com/oracle/graal/lir/cfg/Block.java graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/NewArrayNode.java graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/util/GraphUtil.java graal/com.oracle.graal.printer/src/com/oracle/graal/printer/IdealGraphPrinter.java |
diffstat | 143 files changed, 5615 insertions(+), 3499 deletions(-) [+] |
line wrap: on
line diff
--- a/GRAAL_AUTHORS Mon Jul 09 14:15:55 2012 +0200 +++ b/GRAAL_AUTHORS Mon Jul 09 14:22:22 2012 +0200 @@ -1,5 +1,7 @@ Gilles Duboscq (gdub) Peter Hofer +Alexander Stipsits +Katrin Strassl Christian Humer (chumer) Christian Wimmer (cwimmer) Doug Simon (dnsimon)
--- a/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/Address.java Mon Jul 09 14:15:55 2012 +0200 +++ b/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/Address.java Mon Jul 09 14:22:22 2012 +0200 @@ -45,7 +45,8 @@ private final int displacement; /** - * Creates a {@code CiAddress} with given base register, no scaling and no displacement. + * Creates an {@link Address} with given base register, no scaling and no displacement. + * * @param kind the kind of the value being addressed * @param base the base register */ @@ -54,7 +55,8 @@ } /** - * Creates a {@code CiAddress} with given base register, no scaling and a given displacement. + * Creates an {@link Address} with given base register, no scaling and a given displacement. + * * @param kind the kind of the value being addressed * @param base the base register * @param displacement the displacement @@ -64,8 +66,9 @@ } /** - * Creates a {@code CiAddress} with given base and index registers, scaling and displacement. - * This is the most general constructor.. + * Creates an {@link Address} with given base and index registers, scaling and displacement. + * This is the most general constructor. + * * @param kind the kind of the value being addressed * @param base the base register * @param index the index register
--- a/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/BailoutException.java Mon Jul 09 14:15:55 2012 +0200 +++ b/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/BailoutException.java Mon Jul 09 14:22:22 2012 +0200 @@ -25,7 +25,7 @@ import java.util.*; /** - * {@code CiBailout} is thrown when the compiler refuses to compile a method because of problems with the method. + * Exception thrown when the compiler refuses to compile a method because of problems with the method. * e.g. bytecode wouldn't verify, too big, JSR/ret too complicated, etc. This exception is <i>not</i> * meant to indicate problems with the compiler itself. */ @@ -34,7 +34,8 @@ public static final long serialVersionUID = 8974598793458772L; /** - * Create a new {@code CiBailout}. + * Creates a new {@link BailoutException}. + * * @param reason a message indicating the reason */ public BailoutException(String reason) { @@ -42,7 +43,8 @@ } /** - * Create a new {@code CiBailout}. + * Creates a new {@link BailoutException}. + * * @param args parameters to the formatter */ public BailoutException(String format, Object... args) { @@ -50,7 +52,8 @@ } /** - * Create a new {@code CiBailout} t due to an internal exception being thrown. + * Creates a new {@link BailoutException} due to an internal exception being thrown. + * * @param reason a message indicating the reason * @param cause the throwable that was the cause of the bailout */
--- a/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/CodeCacheProvider.java Mon Jul 09 14:15:55 2012 +0200 +++ b/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/CodeCacheProvider.java Mon Jul 09 14:22:22 2012 +0200 @@ -44,14 +44,6 @@ String disassemble(CodeInfo code, CompilationResult tm); /** - * Returns the disassembly of the given method in a {@code javap}-like format. - * - * @param method the method that should be disassembled - * @return the disassembly. This will be of length 0 if the runtime does not support disassembling. - */ - String disassemble(ResolvedJavaMethod method); - - /** * Gets the register configuration to use when compiling a given method. * * @param method the top level method of a compilation @@ -85,14 +77,15 @@ long getMaxCallTargetOffset(RuntimeCall rtcall); /** - * Adds the given machine code as an implementation of the given method without making it the default implementation. + * Adds the given compilation result as an implementation of the given method without making it the default implementation. + * * @param method a method to which the executable code is begin added - * @param code the code to be added + * @param compResult the compilation result to be added * @param info the object into which details of the installed code will be written. * Ignored if null, otherwise the info is written to index 0 of this array. * @return a reference to the compiled and ready-to-run code */ - InstalledCode addMethod(ResolvedJavaMethod method, CompilationResult code, CodeInfo[] info); + InstalledCode addMethod(ResolvedJavaMethod method, CompilationResult compResult, CodeInfo[] info); /** * Encodes a deoptimization action and a deoptimization reason in an integer value. @@ -101,14 +94,16 @@ int encodeDeoptActionAndReason(DeoptimizationAction action, DeoptimizationReason reason); /** - * Converts a RiDeoptReason into an integer value. - * @return An integer value representing the given RiDeoptReason. + * Converts a {@link DeoptimizationReason} into an integer value. + * + * @return an integer value representing the given {@link DeoptimizationReason} */ int convertDeoptReason(DeoptimizationReason reason); /** - * Converts a RiDeoptAction into an integer value. - * @return An integer value representing the given RiDeoptAction. + * Converts a {@link DeoptimizationAction} into an integer value. + * + * @return an integer value representing the given {@link DeoptimizationAction} */ int convertDeoptAction(DeoptimizationAction action); }
--- a/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/DebugInfo.java Mon Jul 09 14:15:55 2012 +0200 +++ b/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/DebugInfo.java Mon Jul 09 14:22:22 2012 +0200 @@ -38,7 +38,7 @@ private final BitSet frameRefMap; /** - * Creates a new {@code CiDebugInfo} from the given values. + * Creates a new {@link DebugInfo} from the given values. * * @param codePos the {@linkplain BytecodePosition code position} or {@linkplain BytecodeFrame frame} info * @param registerRefMap the register map
--- a/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/Register.java Mon Jul 09 14:15:55 2012 +0200 +++ b/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/Register.java Mon Jul 09 14:22:22 2012 +0200 @@ -104,7 +104,7 @@ } /** - * Creates a {@code CiRegister} instance. + * Creates a {@link Register} instance. * * @param number unique identifier for the register * @param encoding the target machine encoding for the register
--- a/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/RegisterValue.java Mon Jul 09 14:15:55 2012 +0200 +++ b/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/RegisterValue.java Mon Jul 09 14:22:22 2012 +0200 @@ -25,8 +25,8 @@ import com.oracle.graal.api.meta.*; /** - * Denotes a register that stores a value of a fixed kind. There is exactly one (canonical) instance of {@code - * CiRegisterValue} for each ({@link Register}, {@link Kind}) pair. Use {@link Register#asValue(Kind)} to + * Denotes a register that stores a value of a fixed kind. There is exactly one (canonical) instance of {@link + * RegisterValue} for each ({@link Register}, {@link Kind}) pair. Use {@link Register#asValue(Kind)} to * retrieve the canonical {@link RegisterValue} instance for a given (register,kind) pair. */ public final class RegisterValue extends Value {
--- a/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/TargetDescription.java Mon Jul 09 14:15:55 2012 +0200 +++ b/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/TargetDescription.java Mon Jul 09 14:22:22 2012 +0200 @@ -53,7 +53,7 @@ public final int wordSize; /** - * The CiKind to be used for representing raw pointers and CPU registers. + * The kind to be used for representing raw pointers and CPU registers. */ public final Kind wordKind;
--- a/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/VirtualObject.java Mon Jul 09 14:15:55 2012 +0200 +++ b/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/VirtualObject.java Mon Jul 09 14:22:22 2012 +0200 @@ -36,12 +36,17 @@ private final int id; /** - * Creates a new CiVirtualObject for the given type, with the given fields. If the type is an instance class then the values array needs to have one entry for each field, ordered in - * like the fields returned by {@link ResolvedJavaType#declaredFields()}. If the type is an array then the length of the values array determines the reallocated array length. - * @param type the type of the object whose allocation was removed during compilation. This can be either an instance of an array type. + * Creates a new {@link VirtualObject} for the given type, with the given fields. If the type is an instance class + * then the values array needs to have one entry for each field, ordered in like the fields returned by + * {@link ResolvedJavaType#declaredFields()}. If the type is an array then the length of the values array determines + * the reallocated array length. + * + * @param type the type of the object whose allocation was removed during compilation. This can be either an + * instance of an array type. * @param values an array containing all the values to be stored into the object when it is recreated. - * @param id a unique id that identifies the object within the debug information for one position in the compiled code. - * @return a new CiVirtualObject instance. + * @param id a unique id that identifies the object within the debug information for one position in the compiled + * code. + * @return a new {@link VirtualObject} instance. */ public static VirtualObject get(JavaType type, Value[] values, int id) { return new VirtualObject(type, values, id);
--- a/graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/Constant.java Mon Jul 09 14:15:55 2012 +0200 +++ b/graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/Constant.java Mon Jul 09 14:22:22 2012 +0200 @@ -397,6 +397,7 @@ /** * Creates a boxed object constant. + * * @param o the object value to box * @return a boxed copy of {@code value} */ @@ -410,8 +411,9 @@ /** * Creates a boxed constant for the given kind from an Object. * The object needs to be of the Java boxed type corresponding to the kind. + * * @param kind the kind of the constant to create - * @param value the Java boxed value: a Byte instance for CiKind Byte, etc. + * @param value the Java boxed value: a {@link Byte} instance for {@link Kind#Byte}, etc. * @return the boxed copy of {@code value} */ public static Constant forBoxed(Kind kind, Object value) {
--- a/graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/JavaType.java Mon Jul 09 14:15:55 2012 +0200 +++ b/graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/JavaType.java Mon Jul 09 14:22:22 2012 +0200 @@ -65,7 +65,9 @@ /** * For array types, gets the type of the components. - * @return the component type of this array type + * This will be null if this is not an array type. + * + * @return the component type of this type if it is an array type otherwise null */ JavaType componentType();
--- a/graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/MetaUtil.java Mon Jul 09 14:15:55 2012 +0200 +++ b/graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/MetaUtil.java Mon Jul 09 14:22:22 2012 +0200 @@ -25,6 +25,7 @@ import static java.lang.reflect.Modifier.*; import java.lang.annotation.*; +import java.lang.reflect.*; import java.util.*; import com.oracle.graal.api.meta.JavaTypeProfile.ProfiledType; @@ -308,6 +309,27 @@ /** + * Gets the annotations of a particular type for the formal parameters of a given method. + * + * @param annotationClass the Class object corresponding to the annotation type + * @param method the method for which a parameter annotations are being requested + * @return the annotation of type {@code annotationClass} (if any) for each formal parameter present + */ + public static <T extends Annotation> T[] getParameterAnnotations(Class<T> annotationClass, ResolvedJavaMethod method) { + Annotation[][] parameterAnnotations = method.getParameterAnnotations(); + @SuppressWarnings("unchecked") + T[] result = (T[]) Array.newInstance(annotationClass, parameterAnnotations.length); + for (int i = 0; i < parameterAnnotations.length; i++) { + for (Annotation a : parameterAnnotations[i]) { + if (a.annotationType() == annotationClass) { + result[i] = annotationClass.cast(a); + } + } + } + return result; + } + + /** * Gets the annotation of a particular type for a formal parameter of a given method. * * @param annotationClass the Class object corresponding to the annotation type @@ -328,7 +350,6 @@ return null; } - /** * Convenient shortcut for calling {@link #appendLocation(StringBuilder, ResolvedJavaMethod, int)} without having to supply a * a {@link StringBuilder} instance and convert the result to a string. @@ -348,7 +369,8 @@ * java.lang.String.valueOf(String.java:2930) [bci: 12] * </pre> * - * Otherwise, the string returned is the value of {@code CiUtil.format("%H.%n(%p)"}, suffixed by the bci location. + * Otherwise, the string returned is the value of applying {@link #format(String, JavaMethod)} + * with the format string {@code "%H.%n(%p)"}, suffixed by the bci location. * For example: * * <pre>
--- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/GraalCompiler.java Mon Jul 09 14:15:55 2012 +0200 +++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/GraalCompiler.java Mon Jul 09 14:22:22 2012 +0200 @@ -59,14 +59,14 @@ /** * The XIR generator that lowers Java operations to machine operations. */ - public final RiXirGenerator xir; + public final XirGenerator xir; /** * The backend that this compiler has been configured for. */ public final Backend backend; - public GraalCompiler(GraalCodeCacheProvider runtime, TargetDescription target, Backend backend, RiXirGenerator xirGen) { + public GraalCompiler(GraalCodeCacheProvider runtime, TargetDescription target, Backend backend, XirGenerator xirGen) { this.runtime = runtime; this.target = target; this.xir = xirGen; @@ -170,9 +170,17 @@ new LoweringPhase(runtime, assumptions).apply(graph); + if (GraalOptions.OptTailDuplication) { + new TailDuplicationPhase().apply(graph); + if (GraalOptions.OptCanonicalizer) { + new CanonicalizerPhase(target, runtime, assumptions).apply(graph); + } + } + if (GraalOptions.CullFrameStates) { new CullFrameStatesPhase().apply(graph); } + new FloatingReadPhase().apply(graph); if (GraalOptions.OptGVN) { new GlobalValueNumberingPhase().apply(graph);
--- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/GraalOptions.java Mon Jul 09 14:15:55 2012 +0200 +++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/GraalOptions.java Mon Jul 09 14:22:22 2012 +0200 @@ -71,6 +71,8 @@ public static int ForcedInlineEscapeWeight = 10; public static boolean PrintEscapeAnalysis = ____; + public static double TailDuplicationProbability = 0.5; + // absolute probability analysis public static boolean ProbabilityAnalysis = true; public static int LoopFrequencyPropagationPolicy = -2; @@ -212,7 +214,7 @@ public static boolean OptLivenessAnalysis = true; public static boolean OptLoopTransform = true; public static boolean OptSafepointElimination = true; - public static boolean FloatingReads = true; + public static boolean OptTailDuplication = true; /** * Insert a counter in the method prologue to track the most frequently called methods that were compiled by Graal. @@ -234,9 +236,9 @@ public static boolean PrintFlags = false; /** - * Counts the various paths taken through a compiled checkcast. + * Counts the various paths taken through snippets. */ - public static boolean CheckcastCounters = false; + public static boolean SnippetCounters = false; /** * If the probability that a checkcast will hit one the profiled types (up to {@link #CheckcastMaxHints}) @@ -267,6 +269,7 @@ */ public static String HIRLowerCheckcast = ""; public static String HIRLowerNewInstance = ""; + public static String HIRLowerNewArray = ""; static { // turn detailed assertions on when the general assertions are on (misusing the assert keyword for this)
--- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/alloc/ComputeLinearScanOrder.java Mon Jul 09 14:15:55 2012 +0200 +++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/alloc/ComputeLinearScanOrder.java Mon Jul 09 14:22:22 2012 +0200 @@ -27,6 +27,7 @@ import com.oracle.max.criutils.*; import com.oracle.graal.compiler.*; +import com.oracle.graal.compiler.util.*; import com.oracle.graal.graph.*; import com.oracle.graal.lir.cfg.*; import com.oracle.graal.nodes.*; @@ -304,15 +305,21 @@ Block cur = workList.remove(workList.size() - 1); appendBlock(cur); - // make the most successor with the highest probability the immediate successor Node endNode = cur.getEndNode(); - if (endNode instanceof IfNode && ((IfNode) endNode).probability() < 0.5) { - assert cur.numberOfSux() == 2; - if (readyForProcessing(cur.suxAt(1))) { - sortIntoWorkList(cur.suxAt(1)); - } - if (readyForProcessing(cur.suxAt(0))) { - sortIntoWorkList(cur.suxAt(0)); + if (endNode instanceof ControlSplitNode) { + // Sort the successors according to their probabilities: + final ControlSplitNode split = (ControlSplitNode) endNode; + Integer[] indexes = Util.createSortedPermutation(split.blockSuccessorCount(), new Comparator<Integer>() { + @Override + public int compare(Integer o1, Integer o2) { + return split.probability(o1) < split.probability(o2) ? 1 : split.probability(o1) > split.probability(o2) ? -1 : 0; + } + }); + for (int index : indexes) { + Block sux = cur.getSuccessors().get(indexes[index]); + if (readyForProcessing(sux)) { + sortIntoWorkList(sux); + } } } else { for (Block sux : cur.getSuccessors()) {
--- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/alloc/ControlFlowOptimizer.java Mon Jul 09 14:15:55 2012 +0200 +++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/alloc/ControlFlowOptimizer.java Mon Jul 09 14:22:22 2012 +0200 @@ -211,7 +211,7 @@ // this may lead to unnecesary return instructions in the final code assert curLastOp.info == null : "return instructions do not have debug information"; - CiValue returnOpr = curLastOp.input(0); + Value returnOpr = curLastOp.input(0); for (int j = block.numberOfPreds() - 1; j >= 0; j--) { LIRBlock pred = block.predAt(j);
--- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/gen/DebugInfoBuilder.java Mon Jul 09 14:15:55 2012 +0200 +++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/gen/DebugInfoBuilder.java Mon Jul 09 14:22:22 2012 +0200 @@ -62,8 +62,8 @@ } current = current.outerFrameState(); } while (current != null); - // fill in the CiVirtualObject values: - // during this process new CiVirtualObjects might be discovered, so repeat until no more changes occur. + // fill in the VirtualObject values: + // during this process new VirtualObjects might be discovered, so repeat until no more changes occur. boolean changed; do { changed = false; @@ -73,7 +73,7 @@ VirtualObjectNode vobj = entry.getKey(); if (vobj instanceof BoxedVirtualObjectNode) { BoxedVirtualObjectNode boxedVirtualObjectNode = (BoxedVirtualObjectNode) vobj; - entry.getValue().setValues(new Value[]{toCiValue(boxedVirtualObjectNode.getUnboxedValue())}); + entry.getValue().setValues(new Value[]{toValue(boxedVirtualObjectNode.getUnboxedValue())}); } else { Value[] values = new Value[vobj.fieldsCount()]; entry.getValue().setValues(values); @@ -82,7 +82,7 @@ VirtualObjectState currentField = objectStates.get(vobj); assert currentField != null; for (int i = 0; i < vobj.fieldsCount(); i++) { - values[i] = toCiValue(currentField.fieldValues().get(i)); + values[i] = toValue(currentField.fieldValues().get(i)); } } } @@ -104,17 +104,17 @@ Value[] values = new Value[numLocals + numStack + numLocks]; for (int i = 0; i < numLocals; i++) { - values[i] = toCiValue(state.localAt(i)); + values[i] = toValue(state.localAt(i)); } for (int i = 0; i < numStack; i++) { - values[numLocals + i] = toCiValue(state.stackAt(i)); + values[numLocals + i] = toValue(state.stackAt(i)); } LockScope nextLock = locks; for (int i = numLocks - 1; i >= 0; i--) { assert locks != null && nextLock.inliningIdentifier == state.inliningIdentifier() && nextLock.stateDepth == i; - Value owner = toCiValue(nextLock.monitor.object()); + Value owner = toValue(nextLock.monitor.object()); Value lockData = nextLock.lockData; boolean eliminated = nextLock.monitor.eliminated(); values[numLocals + numStack + nextLock.stateDepth] = new MonitorValue(owner, lockData, eliminated); @@ -135,7 +135,7 @@ return frame; } - private Value toCiValue(ValueNode value) { + private Value toValue(ValueNode value) { if (value instanceof VirtualObjectNode) { VirtualObjectNode obj = (VirtualObjectNode) value; VirtualObject ciObj = virtualObjects.get(value);
--- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/gen/LIRGenerator.java Mon Jul 09 14:15:55 2012 +0200 +++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/gen/LIRGenerator.java Mon Jul 09 14:22:22 2012 +0200 @@ -31,9 +31,9 @@ import java.util.Map.Entry; import com.oracle.graal.api.code.*; -import com.oracle.graal.api.code.CompilationResult.*; +import com.oracle.graal.api.code.CompilationResult.Mark; import com.oracle.graal.api.meta.*; -import com.oracle.graal.api.meta.JavaType.*; +import com.oracle.graal.api.meta.JavaType.Representation; import com.oracle.graal.compiler.*; import com.oracle.graal.compiler.util.*; import com.oracle.graal.debug.*; @@ -55,13 +55,13 @@ import com.oracle.graal.nodes.type.*; import com.oracle.graal.nodes.virtual.*; import com.oracle.max.asm.*; -import com.oracle.max.cri.xir.CiXirAssembler.XirConstant; -import com.oracle.max.cri.xir.CiXirAssembler.XirInstruction; -import com.oracle.max.cri.xir.CiXirAssembler.XirMark; -import com.oracle.max.cri.xir.CiXirAssembler.XirOperand; -import com.oracle.max.cri.xir.CiXirAssembler.XirParameter; -import com.oracle.max.cri.xir.CiXirAssembler.XirRegister; -import com.oracle.max.cri.xir.CiXirAssembler.XirTemp; +import com.oracle.max.cri.xir.XirAssembler.XirConstant; +import com.oracle.max.cri.xir.XirAssembler.XirInstruction; +import com.oracle.max.cri.xir.XirAssembler.XirMark; +import com.oracle.max.cri.xir.XirAssembler.XirOperand; +import com.oracle.max.cri.xir.XirAssembler.XirParameter; +import com.oracle.max.cri.xir.XirAssembler.XirRegister; +import com.oracle.max.cri.xir.XirAssembler.XirTemp; import com.oracle.max.cri.xir.*; import com.oracle.max.criutils.*; @@ -78,7 +78,7 @@ protected final LIR lir; protected final XirSupport xirSupport; - protected final RiXirGenerator xir; + protected final XirGenerator xir; private final DebugInfoBuilder debugInfoBuilder; private Block currentBlock; @@ -142,7 +142,7 @@ private LockScope curLocks; - public LIRGenerator(Graph graph, CodeCacheProvider runtime, TargetDescription target, FrameMap frameMap, ResolvedJavaMethod method, LIR lir, RiXirGenerator xir, Assumptions assumptions) { + public LIRGenerator(Graph graph, CodeCacheProvider runtime, TargetDescription target, FrameMap frameMap, ResolvedJavaMethod method, LIR lir, XirGenerator xir, Assumptions assumptions) { this.graph = graph; this.runtime = runtime; this.target = target; @@ -343,6 +343,7 @@ if (curLocks == null) { curLocks = predLocks; } else if (curLocks != predLocks && (!pred.isLoopEnd() || predLocks != null)) { +// throw new GraalInternalError("cause: %s", predLocks); throw new BailoutException("unbalanced monitors: predecessor blocks have different monitor states"); } } @@ -504,7 +505,7 @@ } private static boolean canBeNullCheck(LocationNode location) { - // TODO: Make this part of CiTarget + // TODO: Make this part of TargetDescription return !(location instanceof IndexedLocationNode) && location.displacement() < 4096; } @@ -590,7 +591,7 @@ } @Override - public void visitNewTypeArray(NewTypeArrayNode x) { + public void visitNewPrimitiveArray(NewPrimitiveArrayNode x) { XirArgument length = toXirArgument(x.length()); XirSnippet snippet = xir.genNewArray(site(x), length, x.elementType().kind(), null, null); emitXir(snippet, x, state(), true); @@ -1056,11 +1057,7 @@ private void emitSequentialSwitch(final SwitchNode x, Variable key, LabelRef defaultTarget) { int keyCount = x.keyCount(); - Integer[] indexes = new Integer[keyCount]; - for (int i = 0; i < keyCount; i++) { - indexes[i] = i; - } - Arrays.sort(indexes, new Comparator<Integer>() { + Integer[] indexes = Util.createSortedPermutation(keyCount, new Comparator<Integer>() { @Override public int compare(Integer o1, Integer o2) { return x.keyProbability(o1) < x.keyProbability(o2) ? 1 : x.keyProbability(o1) > x.keyProbability(o2) ? -1 : 0;
--- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/phases/CheckCastEliminationPhase.java Mon Jul 09 14:15:55 2012 +0200 +++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/phases/CheckCastEliminationPhase.java Mon Jul 09 14:22:22 2012 +0200 @@ -166,16 +166,16 @@ // this piece of code handles phis (merges the types and knownNull/knownNotNull of the values) if (!(merge instanceof LoopBeginNode)) { for (PhiNode phi : merge.phis()) { - if (phi.type() == PhiType.Value && phi.kind() == CiKind.Object) { + if (phi.type() == PhiType.Value && phi.kind() == Kind.Object) { ValueNode firstValue = phi.valueAt(0); - RiResolvedType type = getNodeType(firstValue); + ResolvedJavaType type = getNodeType(firstValue); boolean notNull = knownNotNull.contains(firstValue); boolean nul = knownNull.contains(firstValue); for (int i = 0; i < withStates.size(); i++) { State otherState = withStates.get(i); ValueNode value = phi.valueAt(i + 1); - RiResolvedType otherType = otherState.getNodeType(value); + ResolvedJavaType otherType = otherState.getNodeType(value); type = widen(type, otherType); notNull &= otherState.knownNotNull.contains(value); nul &= otherState.knownNull.contains(value);
--- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/phases/InliningPhase.java Mon Jul 09 14:15:55 2012 +0200 +++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/phases/InliningPhase.java Mon Jul 09 14:22:22 2012 +0200 @@ -84,10 +84,10 @@ graph.createNodeMap(); if (hints != null) { - scanInvokes((Iterable<? extends Node>) Util.uncheckedCast(this.hints), -1); + scanInvokes((Iterable<? extends Node>) Util.uncheckedCast(this.hints)); } else { - scanInvokes(graph.getNodes(InvokeNode.class), 0); - scanInvokes(graph.getNodes(InvokeWithExceptionNode.class), 0); + scanInvokes(graph.getNodes(InvokeNode.class)); + scanInvokes(graph.getNodes(InvokeWithExceptionNode.class)); } while (!inlineCandidates.isEmpty() && graph.getNodeCount() < GraalOptions.MaximumDesiredSize) { @@ -131,7 +131,7 @@ } if (newNodes != null && info.level < GraalOptions.MaximumInlineLevel) { - scanInvokes(newNodes, info.level + 1); + scanInvokes(newNodes); } } } @@ -149,17 +149,17 @@ } } - private void scanInvokes(final Iterable<? extends Node> nodes, final int level) { + private void scanInvokes(final Iterable<? extends Node> nodes) { Debug.scope("InliningDecisions", new Runnable() { public void run() { for (Node node : nodes) { if (node != null) { if (node instanceof Invoke) { Invoke invoke = (Invoke) node; - scanInvoke(invoke, level); + scanInvoke(invoke); } for (Node usage : node.usages().filterInterface(Invoke.class).snapshot()) { - scanInvoke((Invoke) usage, level); + scanInvoke((Invoke) usage); } } } @@ -167,10 +167,9 @@ }); } - private void scanInvoke(Invoke invoke, int level) { - InlineInfo info = InliningUtil.getInlineInfo(invoke, level >= 0 ? level : computeInliningLevel(invoke), runtime, assumptions, this, optimisticOpts); + private void scanInvoke(Invoke invoke) { + InlineInfo info = InliningUtil.getInlineInfo(invoke, computeInliningLevel(invoke), runtime, assumptions, this, optimisticOpts); if (info != null) { - assert level == -1 || computeInliningLevel(invoke) == level : "outer FramesStates must match inlining level"; metricInliningConsidered.increment(); inlineCandidates.add(info); } @@ -260,13 +259,13 @@ } private static int computeInliningLevel(Invoke invoke) { - int count = 0; + int count = -1; FrameState curState = invoke.stateAfter(); while (curState != null) { count++; curState = curState.outerFrameState(); } - return count - 1; + return count; } private static InliningPolicy createInliningPolicy() {
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/phases/TailDuplicationPhase.java Mon Jul 09 14:22:22 2012 +0200 @@ -0,0 +1,521 @@ +/* + * Copyright (c) 2012, 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. + */ +package com.oracle.graal.compiler.phases; + +import java.util.*; + +import com.oracle.graal.compiler.*; +import com.oracle.graal.debug.*; +import com.oracle.graal.graph.Graph.DuplicationReplacement; +import com.oracle.graal.graph.*; +import com.oracle.graal.nodes.*; +import com.oracle.graal.nodes.VirtualState.NodeClosure; +import com.oracle.graal.nodes.extended.*; +import com.oracle.graal.nodes.java.*; +import com.oracle.graal.nodes.type.*; +import com.oracle.graal.nodes.util.*; + +/** + * This class is a phase that looks for opportunities for tail duplication. The static method + * {@link #tailDuplicate(MergeNode, TailDuplicationDecision, List)} can also be used to drive tail duplication from + * other places, e.g., inlining. + */ +public class TailDuplicationPhase extends Phase { + + /* + * Various metrics on the circumstances in which tail duplication was/wasn't performed. + */ + private static final DebugMetric metricDuplicationMonitors = Debug.metric("DuplicationMonitors"); + private static final DebugMetric metricDuplicationEnd = Debug.metric("DuplicationEnd"); + private static final DebugMetric metricDuplicationEndPerformed = Debug.metric("DuplicationEndPerformed"); + private static final DebugMetric metricDuplicationOther = Debug.metric("DuplicationOther"); + private static final DebugMetric metricDuplicationOtherPerformed = Debug.metric("DuplicationOtherPerformed"); + + /** + * This interface is used by tail duplication to let clients decide if tail duplication should be performed. + */ + public interface TailDuplicationDecision { + + /** + * Queries if tail duplication should be performed at the given merge. If this method returns true then the tail + * duplication will be performed, because all other checks have happened before. + * + * @param merge The merge at which tail duplication can be performed. + * @param fixedNodeCount The size of the set of fixed nodes that forms the base for the duplicated set of nodes. + * @return true if the tail duplication should be performed, false otherwise. + */ + boolean doTransform(MergeNode merge, int fixedNodeCount); + } + + /** + * A tail duplication decision closure that employs the default algorithm: Check if there are any phis on the merge + * whose stamps improve and that have usages within the duplicated set of fixed nodes. + */ + public static final TailDuplicationDecision DEFAULT_DECISION = new TailDuplicationDecision() { + + public boolean doTransform(MergeNode merge, int fixedNodeCount) { + HashSet<PhiNode> improvements = new HashSet<>(); + for (PhiNode phi : merge.phis()) { + Stamp phiStamp = phi.stamp(); + for (ValueNode input : phi.values()) { + if (!input.stamp().equals(phiStamp)) { + improvements.add(phi); + break; + } + } + } + if (improvements.isEmpty()) { + return false; + } + FixedNode current = merge; + int opportunities = 0; + while (current instanceof FixedWithNextNode) { + current = ((FixedWithNextNode) current).next(); + for (PhiNode phi : improvements) { + if (current.inputs().contains(phi)) { + opportunities++; + } + } + } + return opportunities > 0; + } + }; + + /** + * A tail duplication decision closure that always returns true. + */ + public static final TailDuplicationDecision TRUE_DECISION = new TailDuplicationDecision() { + + @Override + public boolean doTransform(MergeNode merge, int fixedNodeCount) { + return true; + } + }; + + @Override + protected void run(StructuredGraph graph) { + // A snapshot is taken here, so that new MergeNode instances aren't considered for tail duplication. + for (MergeNode merge : graph.getNodes(MergeNode.class).snapshot()) { + if (!(merge instanceof LoopBeginNode) && merge.probability() >= GraalOptions.TailDuplicationProbability) { + tailDuplicate(merge, DEFAULT_DECISION, null); + } + } + } + + /** + * This method attempts to duplicate the tail of the given merge. The merge must not be a {@link LoopBeginNode}. If + * the merge is eligible for duplication (at least one fixed node in its tail, no {@link MonitorEnterNode}/ + * {@link MonitorExitNode}, non-null {@link MergeNode#stateAfter()}) then the decision callback is used to determine + * whether the tail duplication should actually be performed. If replacements is non-null, then this list of + * {@link PiNode}s is used to replace one value per merge end. + * + * @param merge The merge whose tail should be duplicated. + * @param decision A callback that can make the final decision if tail duplication should occur or not. + * @param replacements A list of {@link PiNode}s, or null. If this list is non-null then its size needs to match the + * merge's end count. Each entry can either be null or a {@link PiNode}, and is used to replace + * {@link PiNode#object()} with the {@link PiNode} in the duplicated branch that corresponds to the + * entry. + */ + public static void tailDuplicate(MergeNode merge, TailDuplicationDecision decision, List<PiNode> replacements) { + assert !(merge instanceof LoopBeginNode); + assert replacements == null || replacements.size() == merge.forwardEndCount(); + FixedNode fixed = merge; + int fixedCount = 0; + boolean containsMonitor = false; + while (fixed instanceof FixedWithNextNode) { + if (fixed instanceof MonitorEnterNode || fixed instanceof MonitorExitNode) { + containsMonitor = true; + } + fixed = ((FixedWithNextNode) fixed).next(); + fixedCount++; + } + if (containsMonitor) { + // cannot currently be handled + // TODO (ls) re-evaluate this limitation after changes to the lock representation and the LIR generator + metricDuplicationMonitors.increment(); + } else if (fixedCount > 1) { + if (fixed instanceof EndNode && !(((EndNode) fixed).merge() instanceof LoopBeginNode)) { + metricDuplicationEnd.increment(); + if (decision.doTransform(merge, fixedCount)) { + metricDuplicationEndPerformed.add(fixedCount); + new DuplicationOperation(merge, replacements).duplicate(); + } + } else if (merge.stateAfter() != null) { + metricDuplicationOther.increment(); + if (decision.doTransform(merge, fixedCount)) { + metricDuplicationOtherPerformed.add(fixedCount); + new DuplicationOperation(merge, replacements).duplicate(); + } + } + } + } + + /** + * This class encapsulates one tail duplication operation on a specific {@link MergeNode}. + */ + private static class DuplicationOperation { + + private final MergeNode merge; + private final StructuredGraph graph; + + private final HashMap<ValueNode, PhiNode> bottomPhis = new HashMap<>(); + private final List<PiNode> replacements; + + /** + * Initializes the tail duplication operation without actually performing any work. + * + * @param merge The merge whose tail should be duplicated. + * @param replacements A list of replacement {@link PiNode}s, or null. If this is non-null, then the size of the + * list needs to match the number of end nodes at the merge. + */ + public DuplicationOperation(MergeNode merge, List<PiNode> replacements) { + this.merge = merge; + this.replacements = replacements; + this.graph = (StructuredGraph) merge.graph(); + } + + /** + * Performs the actual tail duplication: + * <ul> + * <li>Creates a new {@link ValueAnchorNode} at the beginning of the duplicated area, an transfers all + * dependencies from the merge to this anchor.</li> + * <li>Determines the set of fixed nodes to be duplicated.</li> + * <li>Creates the new merge at the bottom of the duplicated area.</li> + * <li>Determines the complete set of duplicated nodes.</li> + * <li>Performs the actual duplication.</li> + * </ul> + */ + private void duplicate() { + Debug.log("tail duplication at merge %s in %s (prob %f)", merge, graph.method(), merge.probability()); + + ValueAnchorNode anchor = addValueAnchor(); + + // determine the fixed nodes that should be duplicated (currently: all nodes up until the first control + // split, end node, deopt or return. + ArrayList<FixedNode> fixedNodes = new ArrayList<>(); + FixedNode fixed = merge.next(); + FrameState stateAfter = merge.stateAfter(); + while (fixed instanceof FixedWithNextNode) { + fixedNodes.add(fixed); + if (fixed instanceof StateSplit && ((StateSplit) fixed).stateAfter() != null) { + stateAfter = ((StateSplit) fixed).stateAfter(); + } + fixed = ((FixedWithNextNode) fixed).next(); + } + + EndNode endAfter = createNewMerge(fixed, stateAfter); + MergeNode mergeAfter = endAfter.merge(); + fixedNodes.add(endAfter); + final HashSet<Node> duplicatedNodes = buildDuplicatedNodeSet(fixedNodes, stateAfter); + mergeAfter.clearEnds(); + expandDuplicated(duplicatedNodes, mergeAfter); + + List<EndNode> endSnapshot = merge.forwardEnds().snapshot(); + List<PhiNode> phiSnapshot = merge.phis().snapshot(); + + int endIndex = 0; + for (final EndNode forwardEnd : merge.forwardEnds()) { + Map<Node, Node> duplicates; + if (replacements == null || replacements.get(endIndex) == null) { + duplicates = graph.addDuplicates(duplicatedNodes, (DuplicationReplacement) null); + } else { + HashMap<Node, Node> replace = new HashMap<>(); + replace.put(replacements.get(endIndex).object(), replacements.get(endIndex)); + duplicates = graph.addDuplicates(duplicatedNodes, replace); + } + for (Map.Entry<ValueNode, PhiNode> phi : bottomPhis.entrySet()) { + phi.getValue().initializeValueAt(merge.forwardEndIndex(forwardEnd), (ValueNode) duplicates.get(phi.getKey())); + } + mergeAfter.addForwardEnd((EndNode) duplicates.get(endAfter)); + + // re-wire the duplicated ValueAnchorNode to the predecessor of the corresponding EndNode + FixedNode anchorDuplicate = (FixedNode) duplicates.get(anchor); + ((FixedWithNextNode) forwardEnd.predecessor()).setNext(anchorDuplicate); + // move dependencies on the ValueAnchorNode to the previous BeginNode + BeginNode prevBegin = BeginNode.prevBegin(anchorDuplicate); + anchorDuplicate.replaceAtUsages(prevBegin); + + // re-wire the phi duplicates to the correct input + for (PhiNode phi : phiSnapshot) { + PhiNode phiDuplicate = (PhiNode) duplicates.get(phi); + for (Node usage : phiDuplicate.usages()) { + if (usage instanceof ValueNode) { + ((ValueNode) usage).dependencies().add(prevBegin); + } + } + phiDuplicate.replaceAtUsages(phi.valueAt(forwardEnd)); + phiDuplicate.safeDelete(); + } + endIndex++; + } + GraphUtil.killCFG(merge); + for (EndNode forwardEnd : endSnapshot) { + forwardEnd.safeDelete(); + } + for (PhiNode phi : phiSnapshot) { + // these phis should go away, but they still need to be anchored to a merge to be valid... + if (phi.isAlive()) { + phi.setMerge(mergeAfter); + } + } + Debug.dump(graph, "After tail duplication at %s", merge); + } + + /** + * Inserts a new ValueAnchorNode after the merge and transfers all dependency-usages (not phis) to this + * ValueAnchorNode. + * + * @return The new {@link ValueAnchorNode} that was created. + */ + private ValueAnchorNode addValueAnchor() { + ValueAnchorNode anchor = graph.add(new ValueAnchorNode()); + graph.addAfterFixed(merge, anchor); + for (Node usage : merge.usages().snapshot()) { + if (usage instanceof PhiNode && ((PhiNode) usage).merge() == merge) { + // nothing to do + } else { + usage.replaceFirstInput(merge, anchor); + } + } + return anchor; + } + + /** + * Given a set of fixed nodes, this method determines the set of fixed and floating nodes that needs to be + * duplicated, i.e., all nodes that due to data flow and other dependencies needs to be duplicated. + * + * @param fixedNodes The set of fixed nodes that should be duplicated. + * @param stateAfter The frame state of the merge that follows the set of fixed nodes. All {@link ValueNode}s + * reachable from this state are considered to be reachable from within the duplicated set of nodes. + * @return The set of nodes that need to be duplicated. + */ + private HashSet<Node> buildDuplicatedNodeSet(final ArrayList<FixedNode> fixedNodes, FrameState stateAfter) { + final NodeBitMap aboveBound = graph.createNodeBitMap(); + final NodeBitMap belowBound = graph.createNodeBitMap(); + + final Deque<Node> worklist = new ArrayDeque<>(); + + // Build the set of nodes that have (transitive) usages within the duplicatedNodes. + // This is achieved by iterating all nodes that are reachable via inputs from the the fixed nodes. + aboveBound.markAll(fixedNodes); + worklist.addAll(fixedNodes); + + // the phis at the original merge should always be duplicated + for (PhiNode phi : merge.phis()) { + aboveBound.mark(phi); + worklist.add(phi); + } + + NodeClosure<Node> aboveClosure = new NodeClosure<Node>() { + + @Override + public void apply(Node usage, Node node) { + if (node instanceof PhiNode && !fixedNodes.contains(((PhiNode) node).merge())) { + // stop iterating: phis belonging to outside merges are known to be outside. + } else if (node instanceof FixedNode) { + // stop iterating: fixed nodes within the given set are traversal roots anyway, and all other + // fixed nodes are known to be outside. + } else if (!aboveBound.isMarked(node)) { + worklist.add(node); + aboveBound.mark(node); + } + } + }; + + if (stateAfter != null) { + stateAfter.applyToNonVirtual(aboveClosure); + } + while (!worklist.isEmpty()) { + Node current = worklist.remove(); + for (Node input : current.inputs()) { + aboveClosure.apply(current, input); + } + } + + // Build the set of nodes that have (transitive) inputs within the duplicatedNodes. + // This is achieved by iterating all nodes that are reachable via usages from the fixed nodes. + belowBound.markAll(fixedNodes); + worklist.addAll(fixedNodes); + + // the phis at the original merge should always be duplicated + for (PhiNode phi : merge.phis()) { + belowBound.mark(phi); + worklist.add(phi); + } + + while (!worklist.isEmpty()) { + Node current = worklist.remove(); + for (Node usage : current.usages()) { + if (usage instanceof PhiNode && !fixedNodes.contains(((PhiNode) usage).merge())) { + // stop iterating: phis belonging to outside merges are known to be outside. + } else if (usage instanceof FixedNode) { + // stop iterating: fixed nodes within the given set are traversal roots anyway, and all other + // fixed nodes are known to be outside. + } else if (!belowBound.isMarked(usage)) { + worklist.add(usage); + belowBound.mark(usage); + } + } + } + + // build the intersection + belowBound.intersect(aboveBound); + HashSet<Node> result = new HashSet<>(); + for (Node node : belowBound) { + result.add(node); + } + return result; + } + + /** + * Creates a new merge and end node construct at the end of the duplicated area. While it is useless in itself + * (merge with only one end) it simplifies the later duplication step. + * + * @param successor The successor of the duplicated set of nodes, i.e., the first node that should not be + * duplicated. + * @param stateAfterMerge The frame state that should be used for the merge. + * @return The newly created end node. + */ + private EndNode createNewMerge(FixedNode successor, FrameState stateAfterMerge) { + MergeNode newBottomMerge = graph.add(new MergeNode()); + newBottomMerge.setProbability(successor.probability()); + EndNode newBottomEnd = graph.add(new EndNode()); + newBottomMerge.addForwardEnd(newBottomEnd); + newBottomMerge.setStateAfter(stateAfterMerge); + ((FixedWithNextNode) successor.predecessor()).setNext(newBottomEnd); + newBottomMerge.setNext(successor); + return newBottomEnd; + } + + /** + * Expands the set of nodes to be duplicated by looking at a number of conditions: + * <ul> + * <li>{@link ValueNode}s that have usages on the outside need to be replaced with phis for the outside usages.</li> + * <li>Non-{@link ValueNode} nodes that have outside usages (frame states, virtual object states, ...) need to + * be cloned immediately for the outside usages.</li> + * <li>Nodes that have a {@link StampFactory#extension()} or {@link StampFactory#condition()} stamp need to be + * cloned immediately for the outside usages.</li> + * <li>Dependencies into the duplicated nodes will be replaced with dependencies on the merge.</li> + * <li>Outside non-{@link ValueNode}s with usages within the duplicated set of nodes need to also be duplicated. + * </li> + * <li>Outside {@link ValueNode}s with {@link StampFactory#extension()} or {@link StampFactory#condition()} + * stamps that have usages within the duplicated set of nodes need to also be duplicated.</li> + * </ul> + * + * @param duplicatedNodes The set of duplicated nodes that will be modified (expanded). + * @param newBottomMerge The merge that follows the duplicated set of nodes. It will be used for newly created + * phis and to as a target for dependencies that pointed into the duplicated set of nodes. + */ + private void expandDuplicated(HashSet<Node> duplicatedNodes, MergeNode newBottomMerge) { + Deque<Node> worklist = new ArrayDeque<>(duplicatedNodes); + + while (!worklist.isEmpty()) { + Node duplicated = worklist.remove(); + if (hasUsagesOutside(duplicated, duplicatedNodes)) { + boolean cloneForOutsideUsages = false; + if (duplicated instanceof ValueNode) { + ValueNode node = (ValueNode) duplicated; + if (node.stamp() == StampFactory.dependency()) { + // re-route dependencies to the merge + replaceUsagesOutside(node, newBottomMerge, duplicatedNodes); + // TODO(ls) maybe introduce phis for dependencies + } else if (node.stamp() == StampFactory.extension() || node.stamp() == StampFactory.condition()) { + cloneForOutsideUsages = true; + } else { + // introduce a new phi + PhiNode newPhi = bottomPhis.get(node); + if (newPhi == null) { + newPhi = graph.add(new PhiNode(node.kind(), newBottomMerge)); + bottomPhis.put(node, newPhi); + newPhi.addInput(node); + } + replaceUsagesOutside(node, newPhi, duplicatedNodes); + } + } else { + cloneForOutsideUsages = true; + } + if (cloneForOutsideUsages) { + // clone the offending node to the outside + Node newOutsideClone = duplicated.copyWithInputs(); + replaceUsagesOutside(duplicated, newOutsideClone, duplicatedNodes); + // this might cause other nodes to have outside usages, we need to look at those as well + for (Node input : newOutsideClone.inputs()) { + if (duplicatedNodes.contains(input)) { + worklist.add(input); + } + } + } + } + // check if this node has an input that lies outside and cannot be shared + for (Node input : duplicated.inputs()) { + if (!duplicatedNodes.contains(input)) { + boolean duplicateInput = false; + if (input instanceof VirtualState) { + duplicateInput = true; + } else if (input instanceof ValueNode) { + Stamp inputStamp = ((ValueNode) input).stamp(); + if (inputStamp == StampFactory.extension() || inputStamp == StampFactory.condition()) { + duplicateInput = true; + } + } + if (duplicateInput) { + duplicatedNodes.add(input); + worklist.add(input); + } + } + } + } + } + + /** + * Checks if the given node has usages that are not within the given set of nodes. + * + * @param node The node whose usages are checked. + * @param nodeSet The set of nodes that are considered to be "within". + * @return true if the given node has usages on the outside, false otherwise. + */ + private static boolean hasUsagesOutside(Node node, HashSet<Node> nodeSet) { + for (Node usage : node.usages()) { + if (!nodeSet.contains(usage)) { + return true; + } + } + return false; + } + + /** + * Replaces the given node with the given replacement at all usages that are not within the given set of nodes. + * + * @param node The node to be replaced at outside usages. + * @param replacement The node that replaced the given node at outside usages. + * @param nodeSet The set of nodes that are considered to be "within". + */ + private static void replaceUsagesOutside(Node node, Node replacement, HashSet<Node> nodeSet) { + for (Node usage : node.usages().snapshot()) { + if (!nodeSet.contains(usage)) { + usage.replaceFirstInput(node, replacement); + } + } + } + } +}
--- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/target/Backend.java Mon Jul 09 14:15:55 2012 +0200 +++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/target/Backend.java Mon Jul 09 14:22:22 2012 +0200 @@ -72,11 +72,11 @@ return new FrameMap(runtime, target, registerConfig); } - public abstract LIRGenerator newLIRGenerator(Graph graph, FrameMap frameMap, ResolvedJavaMethod method, LIR lir, RiXirGenerator xir, Assumptions assumptions); + public abstract LIRGenerator newLIRGenerator(Graph graph, FrameMap frameMap, ResolvedJavaMethod method, LIR lir, XirGenerator xir, Assumptions assumptions); public abstract TargetMethodAssembler newAssembler(FrameMap frameMap, LIR lir); - public abstract CiXirAssembler newXirAssembler(); + public abstract XirAssembler newXirAssembler(); /** * Emits code to do stack overflow checking.
--- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/target/amd64/AMD64LIRGenerator.java Mon Jul 09 14:15:55 2012 +0200 +++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/target/amd64/AMD64LIRGenerator.java Mon Jul 09 14:22:22 2012 +0200 @@ -32,7 +32,7 @@ import com.oracle.max.asm.*; import com.oracle.max.asm.target.amd64.*; import com.oracle.max.asm.target.amd64.AMD64Assembler.ConditionFlag; -import com.oracle.max.cri.xir.CiXirAssembler.XirMark; +import com.oracle.max.cri.xir.XirAssembler.XirMark; import com.oracle.max.cri.xir.*; import com.oracle.graal.api.code.*; import com.oracle.graal.api.code.CompilationResult.*; @@ -93,7 +93,7 @@ } } - public AMD64LIRGenerator(Graph graph, CodeCacheProvider runtime, TargetDescription target, FrameMap frameMap, ResolvedJavaMethod method, LIR lir, RiXirGenerator xir, Assumptions assumptions) { + public AMD64LIRGenerator(Graph graph, CodeCacheProvider runtime, TargetDescription target, FrameMap frameMap, ResolvedJavaMethod method, LIR lir, XirGenerator xir, Assumptions assumptions) { super(graph, runtime, target, frameMap, method, lir, xir, assumptions); lir.spillMoveFactory = new AMD64SpillMoveFactory(); }
--- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/target/amd64/AMD64XirAssembler.java Mon Jul 09 14:15:55 2012 +0200 +++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/target/amd64/AMD64XirAssembler.java Mon Jul 09 14:22:22 2012 +0200 @@ -32,10 +32,10 @@ import com.oracle.max.cri.xir.*; /** - * AMD64 version of {@link CiXirAssembler}. + * AMD64 version of {@link XirAssembler}. * */ -public class AMD64XirAssembler extends CiXirAssembler { +public class AMD64XirAssembler extends XirAssembler { public AMD64XirAssembler(TargetDescription target) { super(target); } @@ -216,7 +216,7 @@ } @Override - public CiXirAssembler copy() { + public XirAssembler copy() { return new AMD64XirAssembler(target); } }
--- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/target/amd64/AMD64XirOp.java Mon Jul 09 14:15:55 2012 +0200 +++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/target/amd64/AMD64XirOp.java Mon Jul 09 14:22:22 2012 +0200 @@ -39,10 +39,10 @@ import com.oracle.max.asm.target.amd64.*; import com.oracle.max.asm.target.amd64.AMD64Assembler.ConditionFlag; import com.oracle.max.cri.xir.*; -import com.oracle.max.cri.xir.CiXirAssembler.RuntimeCallInformation; -import com.oracle.max.cri.xir.CiXirAssembler.XirInstruction; -import com.oracle.max.cri.xir.CiXirAssembler.XirLabel; -import com.oracle.max.cri.xir.CiXirAssembler.XirMark; +import com.oracle.max.cri.xir.XirAssembler.RuntimeCallInformation; +import com.oracle.max.cri.xir.XirAssembler.XirInstruction; +import com.oracle.max.cri.xir.XirAssembler.XirLabel; +import com.oracle.max.cri.xir.XirAssembler.XirMark; public class AMD64XirOp extends LIRXirInstruction { public AMD64XirOp(XirSnippet snippet, Value[] operands, Value outputOperand, Value[] inputs, Value[] temps, int[] inputOperandIndices, int[] tempOperandIndices, int outputOperandIndex, @@ -179,7 +179,7 @@ } case PointerLoadDisp: { - CiXirAssembler.AddressAccessInformation addressInformation = (CiXirAssembler.AddressAccessInformation) inst.extra; + XirAssembler.AddressAccessInformation addressInformation = (XirAssembler.AddressAccessInformation) inst.extra; boolean canTrap = addressInformation.canTrap; Address.Scale scale = addressInformation.scale; @@ -206,7 +206,7 @@ } case LoadEffectiveAddress: { - CiXirAssembler.AddressAccessInformation addressInformation = (CiXirAssembler.AddressAccessInformation) inst.extra; + XirAssembler.AddressAccessInformation addressInformation = (XirAssembler.AddressAccessInformation) inst.extra; Address.Scale scale = addressInformation.scale; int displacement = addressInformation.disp; @@ -223,7 +223,7 @@ } case PointerStoreDisp: { - CiXirAssembler.AddressAccessInformation addressInformation = (CiXirAssembler.AddressAccessInformation) inst.extra; + XirAssembler.AddressAccessInformation addressInformation = (XirAssembler.AddressAccessInformation) inst.extra; boolean canTrap = addressInformation.canTrap; Address.Scale scale = addressInformation.scale;
--- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/util/InliningUtil.java Mon Jul 09 14:15:55 2012 +0200 +++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/util/InliningUtil.java Mon Jul 09 14:22:22 2012 +0200 @@ -28,13 +28,13 @@ import com.oracle.graal.api.code.*; import com.oracle.graal.api.meta.*; -import com.oracle.graal.api.meta.JavaTypeProfile.*; +import com.oracle.graal.api.meta.JavaTypeProfile.ProfiledType; import com.oracle.graal.compiler.*; import com.oracle.graal.compiler.phases.*; import com.oracle.graal.debug.*; import com.oracle.graal.graph.*; import com.oracle.graal.nodes.*; -import com.oracle.graal.nodes.FrameState.*; +import com.oracle.graal.nodes.FrameState.InliningIdentifier; import com.oracle.graal.nodes.calc.*; import com.oracle.graal.nodes.extended.*; import com.oracle.graal.nodes.java.*; @@ -45,6 +45,8 @@ public class InliningUtil { + private static final DebugMetric metricInliningTailDuplication = Debug.metric("InliningTailDuplication"); + public interface InliningCallback { StructuredGraph buildGraph(ResolvedJavaMethod method); double inliningWeight(ResolvedJavaMethod caller, ResolvedJavaMethod method, Invoke invoke); @@ -270,6 +272,7 @@ private void inlineMultipleMethods(StructuredGraph graph, GraalCodeCacheProvider runtime, InliningCallback callback, int numberOfMethods, boolean hasReturnValue) { FixedNode continuation = invoke.next(); + ValueNode originalReceiver = invoke.callTarget().receiver(); // setup merge and phi nodes for results and exceptions MergeNode returnMerge = graph.add(new MergeNode()); returnMerge.setProbability(invoke.probability()); @@ -329,7 +332,7 @@ GraphUtil.killCFG(invokeWithExceptionNode.exceptionEdge()); } - // replace the invoke with a cascade of if nodes + // replace the invoke with a switch on the type of the actual receiver ReadHubNode objectClassNode = graph.add(new ReadHubNode(invoke.callTarget().receiver())); graph.addBeforeFixed(invoke.node(), objectClassNode); FixedNode dispatchOnType = createDispatchOnType(graph, objectClassNode, calleeEntryNodes, unknownTypeNode); @@ -340,6 +343,8 @@ invoke.node().replaceAtUsages(returnValuePhi); invoke.node().replaceAndDelete(dispatchOnType); + ArrayList<PiNode> replacements = new ArrayList<>(); + // do the actual inlining for every invoke for (int i = 0; i < calleeEntryNodes.length; i++) { BeginNode node = calleeEntryNodes[i]; @@ -347,7 +352,7 @@ ResolvedJavaType commonType = getLeastCommonType(i); ValueNode receiver = invokeForInlining.callTarget().receiver(); - ValueNode anchoredReceiver = createAnchoredReceiver(graph, node, commonType, receiver); + PiNode anchoredReceiver = createAnchoredReceiver(graph, node, commonType, receiver); invokeForInlining.callTarget().replaceFirstInput(receiver, anchoredReceiver); ResolvedJavaMethod concrete = concretes.get(i); @@ -355,6 +360,31 @@ callback.recordMethodContentsAssumption(concrete); assert !IntrinsificationPhase.canIntrinsify(invokeForInlining, concrete, runtime); InliningUtil.inline(invokeForInlining, calleeGraph, false); + replacements.add(anchoredReceiver); + } + if (shouldFallbackToInvoke()) { + replacements.add(null); + } + if (GraalOptions.OptTailDuplication) { + /* + * We might want to perform tail duplication at the merge after a type switch, is there are invokes that would + * benefit from the improvement in type information. + */ + FixedNode current = returnMerge; + int opportunities = 0; + do { + if (current instanceof InvokeNode && ((InvokeNode) current).callTarget().receiver() == originalReceiver) { + opportunities++; + } else if (current.inputs().contains(originalReceiver)) { + opportunities++; + } + current = ((FixedWithNextNode) current).next(); + } while (current instanceof FixedWithNextNode); + if (opportunities > 0) { + metricInliningTailDuplication.increment(); + Debug.log("MultiTypeGuardInlineInfo starting tail duplication (%d opportunities)", opportunities); + TailDuplicationPhase.tailDuplicate(returnMerge, TailDuplicationPhase.TRUE_DECISION, replacements); + } } } @@ -679,7 +709,7 @@ } } - private static ValueNode createAnchoredReceiver(StructuredGraph graph, FixedNode anchor, ResolvedJavaType commonType, ValueNode receiver) { + private static PiNode createAnchoredReceiver(StructuredGraph graph, FixedNode anchor, ResolvedJavaType commonType, ValueNode receiver) { // to avoid that floating reads on receiver fields float above the type check return graph.unique(new PiNode(receiver, anchor, StampFactory.declaredNonNull(commonType))); }
--- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/util/Util.java Mon Jul 09 14:15:55 2012 +0200 +++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/util/Util.java Mon Jul 09 14:22:22 2012 +0200 @@ -336,4 +336,23 @@ public static boolean isFloating(Node n) { return n instanceof FloatingNode; } + + /** + * Creates an array of integers of length "size", in which each number from 0 to (size - 1) occurs exactly once. The + * integers are sorted using the given comparator. This can be used to create a sorting for arrays that cannot be + * modified directly. + * + * @param size The size of the range to be sorted. + * @param comparator A comparator that is used to compare indexes. + * @return An array of integers that contains each number from 0 to (size - 1) exactly once, sorted using the + * comparator. + */ + public static Integer[] createSortedPermutation(int size, Comparator<Integer> comparator) { + Integer[] indexes = new Integer[size]; + for (int i = 0; i < size; i++) { + indexes[i] = i; + } + Arrays.sort(indexes, comparator); + return indexes; + } }
--- a/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/NodeBitMap.java Mon Jul 09 14:15:55 2012 +0200 +++ b/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/NodeBitMap.java Mon Jul 09 14:22:22 2012 +0200 @@ -26,9 +26,7 @@ import com.oracle.graal.graph.iterators.*; - - -public final class NodeBitMap extends AbstractNodeIterable<Node>{ +public final class NodeBitMap extends AbstractNodeIterable<Node> { private final boolean autoGrow; private final BitSet bitMap; private final Graph graph; @@ -98,6 +96,11 @@ bitMap.clear(); } + public void intersect(NodeBitMap other) { + assert graph == other.graph; + bitMap.and(other.bitMap); + } + public void grow(Node node) { nodeCount = Math.max(nodeCount, node.id() + 1); } @@ -120,6 +123,7 @@ } private static class MarkedNodeIterator implements Iterator<Node> { + private final NodeBitMap visited; private Iterator<Node> nodes; private Node nextNode;
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/CompilationTask.java Mon Jul 09 14:15:55 2012 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/CompilationTask.java Mon Jul 09 14:22:22 2012 +0200 @@ -47,19 +47,19 @@ private volatile boolean cancelled; - private final HotSpotGraalRuntime compiler; + private final HotSpotGraalRuntime graalRuntime; private final PhasePlan plan; private final HotSpotResolvedJavaMethod method; private final OptimisticOptimizations optimisticOpts; private final int id; private final int priority; - public static CompilationTask create(HotSpotGraalRuntime compiler, PhasePlan plan, OptimisticOptimizations optimisticOpts, HotSpotResolvedJavaMethod method, int id, int priority) { - return new CompilationTask(compiler, plan, optimisticOpts, method, id, priority); + public static CompilationTask create(HotSpotGraalRuntime graalRuntime, PhasePlan plan, OptimisticOptimizations optimisticOpts, HotSpotResolvedJavaMethod method, int id, int priority) { + return new CompilationTask(graalRuntime, plan, optimisticOpts, method, id, priority); } - private CompilationTask(HotSpotGraalRuntime compiler, PhasePlan plan, OptimisticOptimizations optimisticOpts, HotSpotResolvedJavaMethod method, int id, int priority) { - this.compiler = compiler; + private CompilationTask(HotSpotGraalRuntime graalRuntime, PhasePlan plan, OptimisticOptimizations optimisticOpts, HotSpotResolvedJavaMethod method, int id, int priority) { + this.graalRuntime = graalRuntime; this.plan = plan; this.method = method; this.optimisticOpts = optimisticOpts; @@ -115,9 +115,9 @@ @Override public CompilationResult call() throws Exception { - compiler.evictDeoptedGraphs(); + graalRuntime.evictDeoptedGraphs(); StructuredGraph graph = new StructuredGraph(method); - return compiler.getCompiler().compileMethod(method, graph, -1, compiler.getCache(), plan, optimisticOpts); + return graalRuntime.getCompiler().compileMethod(method, graph, -1, graalRuntime.getCache(), plan, optimisticOpts); } }); } finally { @@ -148,11 +148,11 @@ } private void installMethod(final CompilationResult tm) { - Debug.scope("CodeInstall", new Object[] {new DebugDumpScope(String.valueOf(id), true), compiler.getCompiler(), method}, new Runnable() { + Debug.scope("CodeInstall", new Object[] {new DebugDumpScope(String.valueOf(id), true), graalRuntime.getCompiler(), method}, new Runnable() { @Override public void run() { final CodeInfo[] info = Debug.isDumpEnabled() ? new CodeInfo[1] : null; - compiler.getRuntime().installMethod(method, tm, info); + graalRuntime.getRuntime().installMethod(method, tm, info); if (info != null) { Debug.dump(new Object[] {tm, info[0]}, "After code installation"); }
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotCompilationResult.java Mon Jul 09 14:22:22 2012 +0200 @@ -0,0 +1,87 @@ +/* + * Copyright (c) 2011, 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. + */ +package com.oracle.graal.hotspot; + +import java.util.*; + +import com.oracle.graal.api.code.*; +import com.oracle.graal.api.code.CompilationResult.*; +import com.oracle.graal.hotspot.logging.*; +import com.oracle.graal.hotspot.meta.*; + +/** + * Augments a {@link CompilationResult} with HotSpot-specific information. + */ +public final class HotSpotCompilationResult extends CompilerObject { + + private static final long serialVersionUID = 7807321392203253218L; + public final CompilationResult comp; + public final HotSpotResolvedJavaMethod method; // used only for methods + public final String name; // used only for stubs + + public final Site[] sites; + public final ExceptionHandler[] exceptionHandlers; + + public HotSpotCompilationResult(HotSpotResolvedJavaMethod method, CompilationResult comp) { + this.method = method; + this.comp = comp; + this.name = null; + + sites = getSortedSites(comp); + if (comp.getExceptionHandlers() == null) { + exceptionHandlers = null; + } else { + exceptionHandlers = comp.getExceptionHandlers().toArray(new ExceptionHandler[comp.getExceptionHandlers().size()]); + } + } + + private static Site[] getSortedSites(CompilationResult target) { + List<?>[] lists = new List<?>[] {target.getSafepoints(), target.getDataReferences(), target.getMarks()}; + int count = 0; + for (List<?> list : lists) { + count += list.size(); + } + Site[] result = new Site[count]; + int pos = 0; + for (List<?> list : lists) { + for (Object elem : list) { + result[pos++] = (Site) elem; + } + } + Arrays.sort(result, new Comparator<Site>() { + + public int compare(Site s1, Site s2) { + if (s1.pcOffset == s2.pcOffset && (s1 instanceof Mark ^ s2 instanceof Mark)) { + return s1 instanceof Mark ? -1 : 1; + } + return s1.pcOffset - s2.pcOffset; + } + }); + if (Logger.ENABLED) { + for (Site site : result) { + Logger.log(site.pcOffset + ": " + site); + } + } + return result; + } +}
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotGraalRuntime.java Mon Jul 09 14:15:55 2012 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotGraalRuntime.java Mon Jul 09 14:22:22 2012 +0200 @@ -116,9 +116,9 @@ // these options are important - graal will not generate correct code without them GraalOptions.StackShadowPages = config.stackShadowPages; - RiXirGenerator generator = new HotSpotXirGenerator(config, getTarget(), getRuntime().getGlobalStubRegisterConfig(), this); + XirGenerator generator = new HotSpotXirGenerator(config, getTarget(), getRuntime().getGlobalStubRegisterConfig(), this); if (Logger.ENABLED) { - generator = LoggingProxy.getProxy(RiXirGenerator.class, generator); + generator = LoggingProxy.getProxy(XirGenerator.class, generator); } Backend backend = Backend.create(runtime, target);
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotTargetMethod.java Mon Jul 09 14:15:55 2012 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,87 +0,0 @@ -/* - * Copyright (c) 2011, 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. - */ -package com.oracle.graal.hotspot; - -import java.util.*; - -import com.oracle.graal.api.code.*; -import com.oracle.graal.api.code.CompilationResult.*; -import com.oracle.graal.hotspot.logging.*; -import com.oracle.graal.hotspot.meta.*; - -/** - * CiTargetMethod augmented with HotSpot-specific information. - */ -public final class HotSpotTargetMethod extends CompilerObject { - - private static final long serialVersionUID = 7807321392203253218L; - public final CompilationResult targetMethod; - public final HotSpotResolvedJavaMethod method; // used only for methods - public final String name; // used only for stubs - - public final Site[] sites; - public final ExceptionHandler[] exceptionHandlers; - - public HotSpotTargetMethod(HotSpotResolvedJavaMethod method, CompilationResult targetMethod) { - this.method = method; - this.targetMethod = targetMethod; - this.name = null; - - sites = getSortedSites(targetMethod); - if (targetMethod.getExceptionHandlers() == null) { - exceptionHandlers = null; - } else { - exceptionHandlers = targetMethod.getExceptionHandlers().toArray(new ExceptionHandler[targetMethod.getExceptionHandlers().size()]); - } - } - - private static Site[] getSortedSites(CompilationResult target) { - List<?>[] lists = new List<?>[] {target.getSafepoints(), target.getDataReferences(), target.getMarks()}; - int count = 0; - for (List<?> list : lists) { - count += list.size(); - } - Site[] result = new Site[count]; - int pos = 0; - for (List<?> list : lists) { - for (Object elem : list) { - result[pos++] = (Site) elem; - } - } - Arrays.sort(result, new Comparator<Site>() { - - public int compare(Site s1, Site s2) { - if (s1.pcOffset == s2.pcOffset && (s1 instanceof Mark ^ s2 instanceof Mark)) { - return s1 instanceof Mark ? -1 : 1; - } - return s1.pcOffset - s2.pcOffset; - } - }); - if (Logger.ENABLED) { - for (Site site : result) { - Logger.log(site.pcOffset + ": " + site); - } - } - return result; - } -}
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotVMConfig.java Mon Jul 09 14:15:55 2012 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotVMConfig.java Mon Jul 09 14:22:22 2012 +0200 @@ -22,8 +22,6 @@ */ package com.oracle.graal.hotspot; -import com.oracle.graal.api.meta.*; - /** * Used to communicate configuration details, runtime offsets, etc. to graal upon compileMethod. */ @@ -46,19 +44,66 @@ // offsets, ... public int vmPageSize; public int stackShadowPages; + + /** + * The offset of the mark word in an object's header. + */ + public int markOffset; + + /** + * The offset of the hub/klassOop word in an object's header. + */ public int hubOffset; + + /** + * The offset of an the array length in an array's header. + */ + public int arrayLengthOffset; + + /** + * The offset of the _super_check_offset field in a Klass. + */ public int superCheckOffsetOffset; + + /** + * The offset of the _secondary_super_cache field in a Klass. + */ public int secondarySuperCacheOffset; + + /** + * The offset of the _secondary_supers field in a Klass. + */ public int secondarySupersOffset; - public int arrayLengthOffset; + + /** + * The offset of the _init_state field in an instanceKlass. + */ public int klassStateOffset; + + /** + * The value of instanceKlass::fully_initialized. + */ public int klassStateFullyInitialized; - public int[] arrayOffsets; + + /** + * The value of objArrayKlass::element_klass_offset(). + */ public int arrayClassElementOffset; + + /** + * The value of JavaThread::tlab_top_offset(). + */ public int threadTlabTopOffset; + + /** + * The value of JavaThread::tlab_end_offset(). + */ public int threadTlabEndOffset; + public int threadObjectOffset; + public int instanceHeaderPrototypeOffset; + public int threadExceptionOopOffset; public int threadExceptionPcOffset; public int threadMultiNewArrayStorageOffset; @@ -93,9 +138,6 @@ public long newTypeArrayStub; public long newObjectArrayStub; public long newMultiArrayStub; - public long loadKlassStub; - public long accessFieldStub; - public long resolveStaticCallStub; public long inlineCacheMissStub; public long handleExceptionStub; public long handleDeoptStub; @@ -110,8 +152,4 @@ assert codeEntryAlignment > 0; assert stackShadowPages > 0; } - - public int getArrayOffset(Kind kind) { - return arrayOffsets[kind.ordinal()]; - } }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/MethodFilter.java Mon Jul 09 14:15:55 2012 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/MethodFilter.java Mon Jul 09 14:22:22 2012 +0200 @@ -107,7 +107,7 @@ } public boolean matches(JavaMethod o) { - // check method name first, since CiUtil.toJavaName is expensive + // check method name first, since MetaUtil.toJavaName is expensive if (methodName != null && !methodName.matcher(o.name()).matches()) { return false; }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/bridge/CompilerToVM.java Mon Jul 09 14:15:55 2012 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/bridge/CompilerToVM.java Mon Jul 09 14:22:22 2012 +0200 @@ -63,7 +63,7 @@ void ConstantPool_loadReferencedType(HotSpotResolvedJavaType pool, int cpi, byte byteCode); - HotSpotCompiledMethod installMethod(HotSpotTargetMethod targetMethod, boolean makeDefault, HotSpotCodeInfo info); + HotSpotCompiledMethod installMethod(HotSpotCompilationResult compResult, boolean makeDefault, HotSpotCodeInfo info); HotSpotVMConfig getConfiguration(); @@ -105,8 +105,6 @@ String disassembleNative(byte[] code, long address); - String disassembleJava(HotSpotResolvedJavaMethod method); - StackTraceElement JavaMethod_toStackTraceElement(HotSpotResolvedJavaMethod method, int bci); Object executeCompiledMethod(HotSpotCompiledMethod method, Object arg1, Object arg2, Object arg3);
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/bridge/CompilerToVMImpl.java Mon Jul 09 14:15:55 2012 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/bridge/CompilerToVMImpl.java Mon Jul 09 14:22:22 2012 +0200 @@ -77,7 +77,7 @@ public native JavaField ConstantPool_lookupField(HotSpotResolvedJavaType pool, int cpi, byte byteCode); @Override - public native HotSpotCompiledMethod installMethod(HotSpotTargetMethod targetMethod, boolean makeDefault, HotSpotCodeInfo info); + public native HotSpotCompiledMethod installMethod(HotSpotCompilationResult comp, boolean makeDefault, HotSpotCodeInfo info); @Override public native HotSpotVMConfig getConfiguration(); @@ -150,9 +150,6 @@ public native String disassembleNative(byte[] code, long address); @Override - public native String disassembleJava(HotSpotResolvedJavaMethod method); - - @Override public native StackTraceElement JavaMethod_toStackTraceElement(HotSpotResolvedJavaMethod method, int bci); @Override
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/bridge/VMToCompilerImpl.java Mon Jul 09 14:15:55 2012 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/bridge/VMToCompilerImpl.java Mon Jul 09 14:22:22 2012 +0200 @@ -48,7 +48,7 @@ */ public class VMToCompilerImpl implements VMToCompiler { - private final HotSpotGraalRuntime compiler; + private final HotSpotGraalRuntime graalRuntime; private IntrinsifyArrayCopyPhase intrinsifyArrayCopy; public final HotSpotTypePrimitive typeBoolean; @@ -68,7 +68,7 @@ private PrintStream log = System.out; public VMToCompilerImpl(HotSpotGraalRuntime compiler) { - this.compiler = compiler; + this.graalRuntime = compiler; typeBoolean = new HotSpotTypePrimitive(Kind.Boolean); typeChar = new HotSpotTypePrimitive(Kind.Char); @@ -105,14 +105,15 @@ Debug.setConfig(hotspotDebugConfig); } // Install intrinsics. - final HotSpotRuntime runtime = (HotSpotRuntime) compiler.getCompiler().runtime; + GraalCompiler compiler = graalRuntime.getCompiler(); + final HotSpotRuntime runtime = (HotSpotRuntime) compiler.runtime; if (GraalOptions.Intrinsify) { - Debug.scope("InstallSnippets", new DebugDumpScope("InstallSnippets"), new Runnable() { + Debug.scope("InstallSnippets", new Object[] {new DebugDumpScope("InstallSnippets"), compiler}, new Runnable() { @Override public void run() { VMToCompilerImpl.this.intrinsifyArrayCopy = new IntrinsifyArrayCopyPhase(runtime); - SnippetInstaller installer = new SnippetInstaller(runtime, runtime.getCompiler().getTarget()); + SnippetInstaller installer = new SnippetInstaller(runtime, runtime.getGraalRuntime().getTarget()); GraalIntrinsics.installIntrinsics(installer); runtime.installSnippets(installer); } @@ -214,16 +215,16 @@ CompilationStatistics.clear("bootstrap"); TTY.println(" in %d ms", System.currentTimeMillis() - startTime); - if (compiler.getCache() != null) { - compiler.getCache().clear(); + if (graalRuntime.getCache() != null) { + graalRuntime.getCache().clear(); } System.gc(); CompilationStatistics.clear("bootstrap2"); - MethodEntryCounters.printCounters(compiler); + MethodEntryCounters.printCounters(graalRuntime); } private void enqueue(Method m) throws Throwable { - JavaMethod javaMethod = compiler.getRuntime().getResolvedJavaMethod(m); + JavaMethod javaMethod = graalRuntime.getRuntime().getResolvedJavaMethod(m); assert !Modifier.isAbstract(((HotSpotResolvedJavaMethod) javaMethod).accessFlags()) && !Modifier.isNative(((HotSpotResolvedJavaMethod) javaMethod).accessFlags()) : javaMethod; compileMethod((HotSpotResolvedJavaMethod) javaMethod, 0, false, 10); } @@ -285,9 +286,9 @@ } } CompilationStatistics.clear("final"); - MethodEntryCounters.printCounters(compiler); + MethodEntryCounters.printCounters(graalRuntime); HotSpotXirGenerator.printCounters(TTY.out().out()); - CheckCastSnippets.printCounters(TTY.out().out()); + SnippetCounter.printGroups(TTY.out().out()); } private void flattenChildren(DebugValueMap map, DebugValueMap globalMap) { @@ -374,7 +375,7 @@ final OptimisticOptimizations optimisticOpts = new OptimisticOptimizations(method); int id = compileTaskIds.incrementAndGet(); - CompilationTask task = CompilationTask.create(compiler, createPhasePlan(optimisticOpts), optimisticOpts, method, id, priority); + CompilationTask task = CompilationTask.create(graalRuntime, createPhasePlan(optimisticOpts), optimisticOpts, method, id, priority); if (blocking) { task.runCompilation(); } else { @@ -410,7 +411,7 @@ public JavaField createJavaField(JavaType holder, String name, JavaType type, int offset, int flags) { if (offset != -1) { HotSpotResolvedJavaType resolved = (HotSpotResolvedJavaType) holder; - return resolved.createRiField(name, type, offset, flags); + return resolved.createField(name, type, offset, flags); } return new UnresolvedField(holder, name, type); } @@ -483,7 +484,7 @@ public PhasePlan createPhasePlan(OptimisticOptimizations optimisticOpts) { PhasePlan phasePlan = new PhasePlan(); - GraphBuilderPhase graphBuilderPhase = new GraphBuilderPhase(compiler.getRuntime(), GraphBuilderConfiguration.getDefault(), optimisticOpts); + GraphBuilderPhase graphBuilderPhase = new GraphBuilderPhase(graalRuntime.getRuntime(), GraphBuilderConfiguration.getDefault(), optimisticOpts); phasePlan.addPhase(PhasePosition.AFTER_PARSING, graphBuilderPhase); if (GraalOptions.Intrinsify) { phasePlan.addPhase(PhasePosition.HIGH_LEVEL, intrinsifyArrayCopy);
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotCompiledMethod.java Mon Jul 09 14:15:55 2012 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotCompiledMethod.java Mon Jul 09 14:22:22 2012 +0200 @@ -28,7 +28,7 @@ import com.oracle.graal.hotspot.*; /** - * Implementation of RiCompiledMethod for HotSpot. + * Implementation of {@link InstalledCode} for HotSpot. * Stores a reference to the nmethod which contains the compiled code. * The nmethod also stores a weak reference to the HotSpotCompiledMethod * instance which is necessary to keep the nmethod from being unloaded.
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotConstantPool.java Mon Jul 09 14:15:55 2012 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotConstantPool.java Mon Jul 09 14:22:22 2012 +0200 @@ -26,7 +26,7 @@ import com.oracle.graal.hotspot.*; /** - * Implementation of RiConstantPool for HotSpot. + * Implementation of {@link ConstantPool} for HotSpot. */ public class HotSpotConstantPool extends CompilerObject implements ConstantPool {
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotGraphCache.java Mon Jul 09 14:15:55 2012 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotGraphCache.java Mon Jul 09 14:22:22 2012 +0200 @@ -36,16 +36,16 @@ * This class implements the graph caching system for the HotSpot platform. * * This implementation does not use a map to store the actual cached graphs. The problem is that such maps keep the - * graph, and therefore the RiResolvedMethod referenced from the graph, alive. For some applications and benchmarks this + * graph, and therefore the {@link ResolvedJavaMethod} referenced from the graph, alive. For some applications and benchmarks this * is a problem, e.g., the DaCapoScala "scalatest" benchmark will quickly run out of perm gen because of this. * - * This cannot be solved with a WeakHashMap<RiResolvedMethod, Graph>, since the values within the map will keep the keys + * This cannot be solved with a {@code WeakHashMap<ResolvedJavaMethod, Graph>}, since the values within the map will keep the keys * alive. In order for this to work we would require a weak map in which the "strongness" of the value references * depends upon the reachability of the keys. * - * Therefore the graph cache is implemented in such a way that it stores its cache entries within the RiResolvedMethod. + * Therefore the graph cache is implemented in such a way that it stores its cache entries within the {@link ResolvedJavaMethod}. * It uses the {@link ResolvedJavaMethod#compilerStorage()} map with the HotSpotGraphCache instance as key. - * The cached graph will be kept alive as long as the RiResolvedMethod is alive, but does not prevent the method, and + * The cached graph will be kept alive as long as the {@link ResolvedJavaMethod} is alive, but does not prevent the method, and * therefore the class, from being unloaded. * * The {@link #cachedGraphIds} map is used to find the graphs that should be removed because of deoptimization, and to
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotJavaType.java Mon Jul 09 14:15:55 2012 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotJavaType.java Mon Jul 09 14:22:22 2012 +0200 @@ -26,7 +26,7 @@ import com.oracle.graal.hotspot.*; /** - * Common interface for all HotSpot RiType-implementations. + * Common interface for all HotSpot {@link JavaType} implementations. */ public abstract class HotSpotJavaType extends CompilerObject implements JavaType { private static final long serialVersionUID = -4252886265301910771L;
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotMethodData.java Mon Jul 09 14:15:55 2012 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotMethodData.java Mon Jul 09 14:22:22 2012 +0200 @@ -358,7 +358,7 @@ } totalCount += getTypesNotRecordedExecutionCount(data, position); - return createRiTypeProfile(types, counts, totalCount, entries); + return createTypeProfile(types, counts, totalCount, entries); } protected long getTypesNotRecordedExecutionCount(HotSpotMethodData data, int position) { @@ -367,7 +367,7 @@ return getCounterValue(data, position); } - private static JavaTypeProfile createRiTypeProfile(ResolvedJavaType[] types, long[] counts, long totalCount, int entries) { + private static JavaTypeProfile createTypeProfile(ResolvedJavaType[] types, long[] counts, long totalCount, int entries) { if (entries <= 0 || totalCount < GraalOptions.MatureExecutionsTypeProfile) { return null; }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotMethodUnresolved.java Mon Jul 09 14:15:55 2012 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotMethodUnresolved.java Mon Jul 09 14:22:22 2012 +0200 @@ -25,7 +25,7 @@ import com.oracle.graal.api.meta.*; /** - * Implementation of RiMethod for unresolved HotSpot methods. + * Implementation of {@link JavaMethod} for unresolved HotSpot methods. */ public final class HotSpotMethodUnresolved extends HotSpotMethod { private static final long serialVersionUID = 5610263481791970079L;
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotResolvedJavaMethod.java Mon Jul 09 14:15:55 2012 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotResolvedJavaMethod.java Mon Jul 09 14:22:22 2012 +0200 @@ -34,7 +34,7 @@ import com.oracle.graal.hotspot.counters.*; /** - * Implementation of RiMethod for resolved HotSpot methods. + * Implementation of {@link JavaMethod} for resolved HotSpot methods. */ public final class HotSpotResolvedJavaMethod extends HotSpotMethod implements ResolvedJavaMethod {
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotResolvedJavaType.java Mon Jul 09 14:15:55 2012 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotResolvedJavaType.java Mon Jul 09 14:22:22 2012 +0200 @@ -31,7 +31,7 @@ import com.oracle.graal.hotspot.*; /** - * Implementation of RiType for resolved non-primitive HotSpot classes. + * Implementation of {@link JavaType} for resolved non-primitive HotSpot classes. */ public final class HotSpotResolvedJavaType extends HotSpotJavaType implements ResolvedJavaType { @@ -54,7 +54,11 @@ private ConstantPool constantPool; private boolean isInitialized; private ResolvedJavaType arrayOfType; - private long prototypeHeader; + + /** + * Initial value for the mark word in a new object of this type. + */ + private long initialMarkWord; private HotSpotResolvedJavaType() { throw new GraalInternalError(HotSpotResolvedJavaType.class + " should only be created from C++ code"); @@ -213,7 +217,7 @@ return instanceSize; } - public synchronized ResolvedJavaField createRiField(String fieldName, JavaType type, int offset, int flags) { + public synchronized ResolvedJavaField createField(String fieldName, JavaType type, int offset, int flags) { ResolvedJavaField result = null; long id = offset + ((long) flags << 32); @@ -285,7 +289,7 @@ return superCheckOffset; } - public long prototypeHeader() { - return prototypeHeader; + public long initialMarkWord() { + return initialMarkWord; } }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotRuntime.java Mon Jul 09 14:15:55 2012 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotRuntime.java Mon Jul 09 14:22:22 2012 +0200 @@ -28,10 +28,13 @@ import java.util.*; import com.oracle.graal.api.code.*; -import com.oracle.graal.api.code.CompilationResult.*; -import com.oracle.graal.api.code.CodeUtil.*; +import com.oracle.graal.api.code.CodeUtil.RefMapFormatter; +import com.oracle.graal.api.code.CompilationResult.Call; +import com.oracle.graal.api.code.CompilationResult.DataPatch; +import com.oracle.graal.api.code.CompilationResult.Mark; +import com.oracle.graal.api.code.CompilationResult.Safepoint; import com.oracle.graal.api.meta.*; -import com.oracle.graal.api.meta.JavaType.*; +import com.oracle.graal.api.meta.JavaType.Representation; import com.oracle.graal.compiler.*; import com.oracle.graal.compiler.target.*; import com.oracle.graal.graph.*; @@ -55,13 +58,13 @@ public final HotSpotVMConfig config; final HotSpotRegisterConfig regConfig; private final HotSpotRegisterConfig globalStubRegConfig; - private final HotSpotGraalRuntime compiler; + private final HotSpotGraalRuntime graalRuntime; private CheckCastSnippets.Templates checkcastSnippets; - private NewInstanceSnippets.Templates newInstanceSnippets; + private NewObjectSnippets.Templates newObjectSnippets; - public HotSpotRuntime(HotSpotVMConfig config, HotSpotGraalRuntime compiler) { + public HotSpotRuntime(HotSpotVMConfig config, HotSpotGraalRuntime graalRuntime) { this.config = config; - this.compiler = compiler; + this.graalRuntime = graalRuntime; regConfig = new HotSpotRegisterConfig(config, false); globalStubRegConfig = new HotSpotRegisterConfig(config, true); @@ -73,20 +76,20 @@ installer.install(UnsafeSnippets.class); installer.install(ArrayCopySnippets.class); installer.install(CheckCastSnippets.class); - installer.install(NewInstanceSnippets.class); + installer.install(NewObjectSnippets.class); checkcastSnippets = new CheckCastSnippets.Templates(this); - newInstanceSnippets = new NewInstanceSnippets.Templates(this, config.useTLAB); + newObjectSnippets = new NewObjectSnippets.Templates(this, graalRuntime.getTarget(), config.useTLAB); } - public HotSpotGraalRuntime getCompiler() { - return compiler; + public HotSpotGraalRuntime getGraalRuntime() { + return graalRuntime; } @Override public String disassemble(CodeInfo info, CompilationResult tm) { byte[] code = info.code(); - TargetDescription target = compiler.getTarget(); + TargetDescription target = graalRuntime.getTarget(); HexCodeFile hcf = new HexCodeFile(code, info.start(), target.arch.name, target.wordSize * 8); if (tm != null) { HexCodeFile.addAnnotations(hcf, tm.annotations()); @@ -177,18 +180,13 @@ } @Override - public String disassemble(ResolvedJavaMethod method) { - return compiler.getCompilerToVM().disassembleJava((HotSpotResolvedJavaMethod) method); - } - - @Override public ResolvedJavaType getResolvedJavaType(Kind kind) { - return (ResolvedJavaType) compiler.getCompilerToVM().getType(kind.toJavaClass()); + return (ResolvedJavaType) graalRuntime.getCompilerToVM().getType(kind.toJavaClass()); } @Override public ResolvedJavaType getTypeOf(Constant constant) { - return (ResolvedJavaType) compiler.getCompilerToVM().getJavaType(constant); + return (ResolvedJavaType) graalRuntime.getCompilerToVM().getJavaType(constant); } @Override @@ -199,7 +197,7 @@ @Override public boolean areConstantObjectsEqual(Constant x, Constant y) { - return compiler.getCompilerToVM().compareConstantObjects(x, y); + return graalRuntime.getCompilerToVM().compareConstantObjects(x, y); } @Override @@ -223,7 +221,7 @@ @Override public int getArrayLength(Constant array) { - return compiler.getCompilerToVM().getArrayLength(array); + return graalRuntime.getCompilerToVM().getArrayLength(array); } @Override @@ -373,12 +371,18 @@ } } else if (n instanceof NewInstanceNode) { if (shouldLower(graph, GraalOptions.HIRLowerNewInstance)) { - newInstanceSnippets.lower((NewInstanceNode) n, tool); + newObjectSnippets.lower((NewInstanceNode) n, tool); + } + } else if (n instanceof NewArrayNode) { + if (shouldLower(graph, GraalOptions.HIRLowerNewArray)) { + newObjectSnippets.lower((NewArrayNode) n, tool); } } else if (n instanceof TLABAllocateNode) { - newInstanceSnippets.lower((TLABAllocateNode) n, tool); - } else if (n instanceof InitializeNode) { - newInstanceSnippets.lower((InitializeNode) n, tool); + newObjectSnippets.lower((TLABAllocateNode) n, tool); + } else if (n instanceof InitializeObjectNode) { + newObjectSnippets.lower((InitializeObjectNode) n, tool); + } else if (n instanceof InitializeArrayNode) { + newObjectSnippets.lower((InitializeArrayNode) n, tool); } else { assert false : "Node implementing Lowerable not handled: " + n; } @@ -395,8 +399,8 @@ return false; } - private IndexedLocationNode createArrayLocation(Graph graph, Kind elementKind, ValueNode index) { - return IndexedLocationNode.create(LocationNode.getArrayLocation(elementKind), elementKind, config.getArrayOffset(elementKind), index, graph, true); + private static IndexedLocationNode createArrayLocation(Graph graph, Kind elementKind, ValueNode index) { + return IndexedLocationNode.create(LocationNode.getArrayLocation(elementKind), elementKind, elementKind.arrayBaseOffset(), index, graph, true); } private SafeReadNode safeReadArrayLength(ValueNode array, long leafGraphId) { @@ -470,7 +474,7 @@ } public ResolvedJavaType getResolvedJavaType(Class<?> clazz) { - return (ResolvedJavaType) compiler.getCompilerToVM().getType(clazz); + return (ResolvedJavaType) graalRuntime.getCompilerToVM().getType(clazz); } public Object asCallTarget(Object target) { @@ -478,31 +482,31 @@ } public long getMaxCallTargetOffset(RuntimeCall rtcall) { - return compiler.getCompilerToVM().getMaxCallTargetOffset(rtcall); + return graalRuntime.getCompilerToVM().getMaxCallTargetOffset(rtcall); } public ResolvedJavaMethod getResolvedJavaMethod(Method reflectionMethod) { - return (ResolvedJavaMethod) compiler.getCompilerToVM().getJavaMethod(reflectionMethod); + return (ResolvedJavaMethod) graalRuntime.getCompilerToVM().getJavaMethod(reflectionMethod); } - private static HotSpotCodeInfo makeInfo(ResolvedJavaMethod method, CompilationResult code, CodeInfo[] info) { + private static HotSpotCodeInfo makeInfo(ResolvedJavaMethod method, CompilationResult compResult, CodeInfo[] info) { HotSpotCodeInfo hsInfo = null; if (info != null && info.length > 0) { - hsInfo = new HotSpotCodeInfo(code, (HotSpotResolvedJavaMethod) method); + hsInfo = new HotSpotCodeInfo(compResult, (HotSpotResolvedJavaMethod) method); info[0] = hsInfo; } return hsInfo; } - public void installMethod(ResolvedJavaMethod method, CompilationResult code, CodeInfo[] info) { - HotSpotCodeInfo hsInfo = makeInfo(method, code, info); - compiler.getCompilerToVM().installMethod(new HotSpotTargetMethod((HotSpotResolvedJavaMethod) method, code), true, hsInfo); + public void installMethod(ResolvedJavaMethod method, CompilationResult compResult, CodeInfo[] info) { + HotSpotCodeInfo hsInfo = makeInfo(method, compResult, info); + graalRuntime.getCompilerToVM().installMethod(new HotSpotCompilationResult((HotSpotResolvedJavaMethod) method, compResult), true, hsInfo); } @Override - public InstalledCode addMethod(ResolvedJavaMethod method, CompilationResult code, CodeInfo[] info) { - HotSpotCodeInfo hsInfo = makeInfo(method, code, info); - return compiler.getCompilerToVM().installMethod(new HotSpotTargetMethod((HotSpotResolvedJavaMethod) method, code), false, hsInfo); + public InstalledCode addMethod(ResolvedJavaMethod method, CompilationResult compResult, CodeInfo[] info) { + HotSpotCodeInfo hsInfo = makeInfo(method, compResult, info); + return graalRuntime.getCompilerToVM().installMethod(new HotSpotCompilationResult((HotSpotResolvedJavaMethod) method, compResult), false, hsInfo); } @Override @@ -511,12 +515,6 @@ } @Override - public CompilationResult compile(ResolvedJavaMethod method, StructuredGraph graph) { - OptimisticOptimizations optimisticOpts = OptimisticOptimizations.ALL; - return compiler.getCompiler().compileMethod(method, graph, -1, compiler.getCache(), compiler.getVMToCompiler().createPhasePlan(optimisticOpts), optimisticOpts); - } - - @Override public int encodeDeoptActionAndReason(DeoptimizationAction action, DeoptimizationReason reason) { final int actionShift = 0; final int reasonShift = 3; @@ -528,6 +526,7 @@ @Override public int convertDeoptAction(DeoptimizationAction action) { + // This must be kept in sync with the DeoptAction enum defined in deoptimization.hpp switch(action) { case None: return 0; case RecompileIfTooManyDeopts: return 1; @@ -540,6 +539,7 @@ @Override public int convertDeoptReason(DeoptimizationReason reason) { + // This must be kept in sync with the DeoptReason enum defined in deoptimization.hpp switch(reason) { case None: return 0; case NullCheckException: return 1;
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotTypePrimitive.java Mon Jul 09 14:15:55 2012 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotTypePrimitive.java Mon Jul 09 14:22:22 2012 +0200 @@ -30,7 +30,7 @@ import com.oracle.graal.hotspot.*; /** - * Implementation of RiType for primitive HotSpot types. + * Implementation of {@link JavaType} for primitive HotSpot types. */ public final class HotSpotTypePrimitive extends HotSpotJavaType implements ResolvedJavaType {
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotTypeUnresolved.java Mon Jul 09 14:15:55 2012 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotTypeUnresolved.java Mon Jul 09 14:22:22 2012 +0200 @@ -27,7 +27,7 @@ import com.oracle.graal.hotspot.*; /** - * Implementation of RiType for unresolved HotSpot classes. + * Implementation of {@link JavaType} for unresolved HotSpot classes. */ public class HotSpotTypeUnresolved extends HotSpotJavaType {
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotXirGenerator.java Mon Jul 09 14:15:55 2012 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotXirGenerator.java Mon Jul 09 14:22:22 2012 +0200 @@ -39,13 +39,13 @@ import com.oracle.graal.hotspot.*; import com.oracle.max.asm.target.amd64.*; import com.oracle.max.cri.xir.*; -import com.oracle.max.cri.xir.CiXirAssembler.XirConstant; -import com.oracle.max.cri.xir.CiXirAssembler.XirLabel; -import com.oracle.max.cri.xir.CiXirAssembler.XirMark; -import com.oracle.max.cri.xir.CiXirAssembler.XirOperand; -import com.oracle.max.cri.xir.CiXirAssembler.XirParameter; +import com.oracle.max.cri.xir.XirAssembler.XirConstant; +import com.oracle.max.cri.xir.XirAssembler.XirLabel; +import com.oracle.max.cri.xir.XirAssembler.XirMark; +import com.oracle.max.cri.xir.XirAssembler.XirOperand; +import com.oracle.max.cri.xir.XirAssembler.XirParameter; -public class HotSpotXirGenerator implements RiXirGenerator { +public class HotSpotXirGenerator implements XirGenerator { // this needs to correspond to graal_CodeInstaller.hpp // @formatter:off @@ -77,7 +77,7 @@ private final HotSpotGraalRuntime compiler; - private CiXirAssembler globalAsm; + private XirAssembler globalAsm; public HotSpotXirGenerator(HotSpotVMConfig config, TargetDescription target, RegisterConfig registerConfig, HotSpotGraalRuntime compiler) { this.config = config; @@ -86,7 +86,7 @@ this.compiler = compiler; } - private XirConstant wordConst(CiXirAssembler asm, long value) { + private XirConstant wordConst(XirAssembler asm, long value) { if (target.wordKind == Kind.Long) { return asm.createConstant(Constant.forLong(value)); } else { @@ -107,7 +107,7 @@ private SimpleTemplates invokeInterfaceTemplates = new SimpleTemplates(NULL_CHECK) { @Override - protected XirTemplate create(CiXirAssembler asm, long flags) { + protected XirTemplate create(XirAssembler asm, long flags) { asm.restart(); XirParameter receiver = asm.createInputParameter("receiver", Kind.Object); XirParameter addr = asm.createConstantInputParameter("addr", target.wordKind); @@ -128,7 +128,7 @@ private SimpleTemplates invokeVirtualTemplates = new SimpleTemplates(NULL_CHECK) { @Override - protected XirTemplate create(CiXirAssembler asm, long flags) { + protected XirTemplate create(XirAssembler asm, long flags) { asm.restart(); XirParameter receiver = asm.createInputParameter("receiver", Kind.Object); XirParameter addr = asm.createConstantInputParameter("addr", target.wordKind); @@ -149,7 +149,7 @@ private IndexTemplates inlinedInvokeVirtualTemplates = new IndexTemplates(NULL_CHECK) { @Override - protected XirTemplate create(CiXirAssembler asm, long flags, int vtableEntryOffset) { + protected XirTemplate create(XirAssembler asm, long flags, int vtableEntryOffset) { asm.restart(); XirParameter receiver = asm.createInputParameter("receiver", Kind.Object); XirOperand temp = asm.createRegisterTemp("temp", target.wordKind, AMD64.rax); @@ -174,7 +174,7 @@ private SimpleTemplates invokeSpecialTemplates = new SimpleTemplates(NULL_CHECK) { @Override - protected XirTemplate create(CiXirAssembler asm, long flags) { + protected XirTemplate create(XirAssembler asm, long flags) { asm.restart(); XirParameter receiver = asm.createInputParameter("receiver", Kind.Object); XirParameter addr = asm.createConstantInputParameter("addr", target.wordKind); @@ -203,7 +203,7 @@ private SimpleTemplates invokeStaticTemplates = new SimpleTemplates() { @Override - protected XirTemplate create(CiXirAssembler asm, long flags) { + protected XirTemplate create(XirAssembler asm, long flags) { asm.restart(); XirParameter addr = asm.createConstantInputParameter("addr", target.wordKind); @@ -226,7 +226,7 @@ private SimpleTemplates monitorEnterTemplates = new SimpleTemplates(NULL_CHECK) { @Override - protected XirTemplate create(CiXirAssembler asm, long flags) { + protected XirTemplate create(XirAssembler asm, long flags) { asm.restart(Kind.Void); XirParameter object = asm.createInputParameter("object", Kind.Object); XirParameter lock = asm.createInputParameter("lock", target.wordKind); @@ -265,7 +265,7 @@ private SimpleTemplates monitorExitTemplates = new SimpleTemplates(NULL_CHECK) { @Override - protected XirTemplate create(CiXirAssembler asm, long flags) { + protected XirTemplate create(XirAssembler asm, long flags) { asm.restart(Kind.Void); XirParameter object = asm.createInputParameter("object", Kind.Object); XirParameter lock = asm.createInputParameter("lock", target.wordKind); @@ -288,7 +288,7 @@ private final IndexTemplates newInstanceTemplates = new IndexTemplates() { @Override - protected XirTemplate create(CiXirAssembler asm, long flags, int size) { + protected XirTemplate create(XirAssembler asm, long flags, int size) { XirOperand result = asm.restart(target.wordKind); XirOperand hub = asm.createInputParameter("hub", Kind.Object); @@ -315,7 +315,7 @@ asm.bindInline(resume); asm.pload(target.wordKind, temp1, hub, asm.i(config.instanceHeaderPrototypeOffset), false); - asm.pstore(target.wordKind, result, temp1, false); + asm.pstore(target.wordKind, result, asm.i(config.markOffset), temp1, false); asm.mov(temp1o, hub); // need a temporary register since Intel cannot store 64-bit constants to memory asm.pstore(Kind.Object, result, asm.i(config.hubOffset), temp1o, false); @@ -341,13 +341,13 @@ private SimpleTemplates newObjectArrayTemplates = new SimpleTemplates() { @Override - protected XirTemplate create(CiXirAssembler asm, long flags) { + protected XirTemplate create(XirAssembler asm, long flags) { emitNewTypeArray(asm, Kind.Object, config.useFastNewObjectArray, config.newObjectArrayStub); return asm.finishTemplate("newObjectArray"); } }; - private void emitNewTypeArray(CiXirAssembler asm, Kind kind, boolean useFast, long slowPathStub) { + private void emitNewTypeArray(XirAssembler asm, Kind kind, boolean useFast, long slowPathStub) { XirOperand result = asm.restart(target.wordKind); XirParameter lengthParam = asm.createInputParameter("length", Kind.Int, true); @@ -378,7 +378,7 @@ final int aligning = target.wordSize; final int arrayLengthOffset = target.wordSize * 2; - final int arrayElementOffset = config.getArrayOffset(kind); + final int arrayElementOffset = kind.arrayBaseOffset(); // Calculate aligned size asm.mov(size, length); @@ -401,7 +401,7 @@ // Now the new object is in result, store mark word and klass asm.pload(target.wordKind, temp1, hub, asm.i(config.instanceHeaderPrototypeOffset), false); - asm.pstore(target.wordKind, result, temp1, false); + asm.pstore(target.wordKind, result, asm.i(config.markOffset), temp1, false); asm.mov(temp1o, hub); // need a temporary register since Intel cannot store 64-bit constants to memory asm.pstore(Kind.Object, result, asm.i(config.hubOffset), temp1o, false); @@ -431,7 +431,7 @@ private KindTemplates newTypeArrayTemplates = new KindTemplates() { @Override - protected XirTemplate create(CiXirAssembler asm, long flags, Kind kind) { + protected XirTemplate create(XirAssembler asm, long flags, Kind kind) { emitNewTypeArray(asm, kind, config.useFastNewTypeArray, config.newTypeArrayStub); return asm.finishTemplate("newTypeArray<" + kind.toString() + ">"); } @@ -440,7 +440,7 @@ private final IndexTemplates multiNewArrayTemplate = new IndexTemplates() { @Override - protected XirTemplate create(CiXirAssembler asm, long flags, int dimensions) { + protected XirTemplate create(XirAssembler asm, long flags, int dimensions) { XirOperand result = asm.restart(Kind.Object); XirOperand hub = asm.createRegisterTemp("hub", Kind.Object, AMD64.rax); @@ -485,7 +485,7 @@ private IndexTemplates checkCastTemplates = new IndexTemplates(NULL_CHECK, EXACT_HINTS) { - private void incCounter(CiXirAssembler asm, XirOperand counter, XirParameter counters, CheckcastCounter offset) { + private void incCounter(XirAssembler asm, XirOperand counter, XirParameter counters, CheckcastCounter offset) { int disp = Unsafe.getUnsafe().arrayBaseOffset(long[].class); Scale scale = Scale.fromInt(Unsafe.getUnsafe().arrayIndexScale(long[].class)); XirConstant index = asm.i(offset.ordinal()); @@ -495,10 +495,10 @@ } @Override - protected XirTemplate create(CiXirAssembler asm, long flags, int hintCount) { + protected XirTemplate create(XirAssembler asm, long flags, int hintCount) { asm.restart(Kind.Void); boolean exact = is(EXACT_HINTS, flags); - XirParameter counters = GraalOptions.CheckcastCounters ? asm.createConstantInputParameter("counters", Kind.Object) : null; + XirParameter counters = GraalOptions.SnippetCounters ? asm.createConstantInputParameter("counters", Kind.Object) : null; XirParameter object = asm.createInputParameter("object", Kind.Object); final XirOperand hub = exact ? null : asm.createConstantInputParameter("hub", Kind.Object); @@ -591,7 +591,7 @@ private IndexTemplates instanceOfTemplates = new IndexTemplates(NULL_CHECK, EXACT_HINTS) { @Override - protected XirTemplate create(CiXirAssembler asm, long flags, int hintCount) { + protected XirTemplate create(XirAssembler asm, long flags, int hintCount) { asm.restart(Kind.Void); XirParameter object = asm.createInputParameter("object", Kind.Object); final XirOperand hub = is(EXACT_HINTS, flags) ? null : asm.createConstantInputParameter("hub", Kind.Object); @@ -650,7 +650,7 @@ private IndexTemplates materializeInstanceOfTemplates = new IndexTemplates(NULL_CHECK, EXACT_HINTS) { @Override - protected XirTemplate create(CiXirAssembler asm, long flags, int hintCount) { + protected XirTemplate create(XirAssembler asm, long flags, int hintCount) { XirOperand result = asm.restart(Kind.Int); XirParameter object = asm.createInputParameter("object", Kind.Object); final XirOperand hub = is(EXACT_HINTS, flags) ? null : asm.createConstantInputParameter("hub", Kind.Object); @@ -716,7 +716,7 @@ private SimpleTemplates typeCheckTemplates = new SimpleTemplates(NULL_CHECK) { @Override - protected XirTemplate create(CiXirAssembler asm, long flags) { + protected XirTemplate create(XirAssembler asm, long flags) { asm.restart(Kind.Void); XirParameter objHub = asm.createInputParameter("objectHub", Kind.Object); XirOperand hub = asm.createConstantInputParameter("hub", Kind.Object); @@ -807,7 +807,7 @@ @Override public XirSnippet genCheckCast(XirSite site, XirArgument receiver, XirArgument hub, ResolvedJavaType type, JavaTypeProfile profile) { - final boolean useCounters = GraalOptions.CheckcastCounters; + final boolean useCounters = GraalOptions.SnippetCounters; TypeCheckHints hints = new TypeCheckHints(type, profile, site.assumptions(), GraalOptions.CheckcastMinHintHitProbability, GraalOptions.CheckcastMaxHints); int hintsLength = hints.types.length; if (hintsLength == 0) { @@ -891,11 +891,11 @@ } @Override - public void initialize(CiXirAssembler asm) { + public void initialize(XirAssembler asm) { this.globalAsm = asm; } - private void checkSubtype(CiXirAssembler asm, XirOperand result, XirOperand objHub, XirOperand hub) { + private void checkSubtype(XirAssembler asm, XirOperand result, XirOperand objHub, XirOperand hub) { asm.push(objHub); asm.push(hub); asm.callRuntime(config.instanceofStub, null); @@ -903,7 +903,7 @@ asm.pop(result); } - private static void useRegisters(CiXirAssembler asm, Register... registers) { + private static void useRegisters(XirAssembler asm, Register... registers) { if (registers != null) { for (Register register : registers) { asm.createRegisterTemp("reg", Kind.Illegal, register); @@ -931,7 +931,7 @@ this.mask = getBits((int) INDEX_MASK, null, flags); } - protected abstract XirTemplate create(CiXirAssembler asm, long flags); + protected abstract XirTemplate create(XirAssembler asm, long flags); protected long getBits(int index, XirSite site, TemplateFlag... flags) { long bits = index; @@ -979,11 +979,11 @@ } @Override - protected final XirTemplate create(CiXirAssembler asm, long flags) { + protected final XirTemplate create(XirAssembler asm, long flags) { return create(asm, flags & FLAGS_MASK, (int) (flags & INDEX_MASK)); } - protected abstract XirTemplate create(CiXirAssembler asm, long flags, int index); + protected abstract XirTemplate create(XirAssembler asm, long flags, int index); public XirTemplate get(XirSite site, int size, TemplateFlag... flags) { return getInternal(getBits(size, site, flags)); @@ -997,11 +997,11 @@ } @Override - protected final XirTemplate create(CiXirAssembler asm, long flags) { + protected final XirTemplate create(XirAssembler asm, long flags) { return create(asm, flags & FLAGS_MASK, Kind.VALUES[(int) (flags & INDEX_MASK)]); } - protected abstract XirTemplate create(CiXirAssembler asm, long flags, Kind kind); + protected abstract XirTemplate create(XirAssembler asm, long flags, Kind kind); public XirTemplate get(XirSite site, Kind kind, TemplateFlag... flags) { return getInternal(getBits(kind.ordinal(), site, flags)); @@ -1042,7 +1042,7 @@ } public static void printCounters(PrintStream out) { - if (GraalOptions.CheckcastCounters) { + if (GraalOptions.SnippetCounters) { printCheckcastCounters(out); } }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/CastFromHub.java Mon Jul 09 14:15:55 2012 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/CastFromHub.java Mon Jul 09 14:22:22 2012 +0200 @@ -32,7 +32,7 @@ import com.oracle.graal.nodes.type.*; /** - * This node is used by the {@link NewInstanceSnippets} to give a formatted new instance its exact type. + * This node is used by the {@link NewObjectSnippets} to give a formatted new instance or object its exact type. */ public final class CastFromHub extends FloatingNode implements Canonicalizable {
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/InitializeArrayNode.java Mon Jul 09 14:22:22 2012 +0200 @@ -0,0 +1,77 @@ +/* + * Copyright (c) 2012, 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. + */ +package com.oracle.graal.hotspot.nodes; + +import com.oracle.graal.api.meta.*; +import com.oracle.graal.nodes.*; +import com.oracle.graal.nodes.spi.*; +import com.oracle.graal.nodes.type.*; + +/** + * Initializes the header and body of an uninitialized array cell. + * This node calls out to a stub to do both the allocation and formatting + * if the memory address it is given is zero/null (e.g. due to + * {@linkplain TLABAllocateNode TLAB allocation} failing). + */ +public final class InitializeArrayNode extends FixedWithNextNode implements Lowerable { + + @Input private final ValueNode memory; + @Input private final ValueNode length; + @Input private final ValueNode size; + private final ResolvedJavaType type; + + public InitializeArrayNode(ValueNode memory, ValueNode length, ValueNode size, ResolvedJavaType type) { + super(StampFactory.exactNonNull(type)); + this.memory = memory; + this.type = type; + this.length = length; + this.size = size; + } + + public ValueNode memory() { + return memory; + } + + public ValueNode length() { + return length; + } + + public ValueNode size() { + return size; + } + + public ResolvedJavaType type() { + return type; + } + + @Override + public void lower(LoweringTool tool) { + tool.getRuntime().lower(this, tool); + } + + @SuppressWarnings("unused") + @NodeIntrinsic + public static Object initialize(Object memory, int length, int size, @ConstantNodeParameter ResolvedJavaType type) { + throw new UnsupportedOperationException(); + } +}
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/InitializeNode.java Mon Jul 09 14:15:55 2012 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,65 +0,0 @@ -/* - * Copyright (c) 2012, 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. - */ -package com.oracle.graal.hotspot.nodes; - -import com.oracle.graal.api.meta.*; -import com.oracle.graal.nodes.*; -import com.oracle.graal.nodes.spi.*; -import com.oracle.graal.nodes.type.*; - -/** - * Initializes the header and body of an uninitialized object cell. - * This node calls out to a stub to do both the allocation and formatting - * if the memory address it is given is zero/null (e.g. due to - * {@linkplain TLABAllocateNode TLAB allocation} failing). - */ -public final class InitializeNode extends FixedWithNextNode implements Lowerable { - - @Input private final ValueNode memory; - private final ResolvedJavaType type; - - public InitializeNode(ValueNode memory, ResolvedJavaType type) { - super(StampFactory.exactNonNull(type)); - this.memory = memory; - this.type = type; - } - - public ValueNode memory() { - return memory; - } - - public ResolvedJavaType type() { - return type; - } - - @Override - public void lower(LoweringTool tool) { - tool.getRuntime().lower(this, tool); - } - - @SuppressWarnings("unused") - @NodeIntrinsic - public static Object initialize(Object memory, @ConstantNodeParameter ResolvedJavaType type) { - throw new UnsupportedOperationException(); - } -}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/InitializeObjectNode.java Mon Jul 09 14:22:22 2012 +0200 @@ -0,0 +1,59 @@ +/* + * Copyright (c) 2012, 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. + */ +package com.oracle.graal.hotspot.nodes; + +import com.oracle.graal.api.meta.*; +import com.oracle.graal.nodes.*; +import com.oracle.graal.nodes.spi.*; +import com.oracle.graal.nodes.type.*; + +/** + * Initializes the header and body of an uninitialized object cell. + * This node calls out to a stub to do both the allocation and formatting + * if the memory address it is given is zero/null (e.g. due to + * {@linkplain TLABAllocateNode TLAB allocation} failing). + */ +public final class InitializeObjectNode extends FixedWithNextNode implements Lowerable { + + @Input private final ValueNode memory; + private final ResolvedJavaType type; + + public InitializeObjectNode(ValueNode memory, ResolvedJavaType type) { + super(StampFactory.exactNonNull(type)); + this.memory = memory; + this.type = type; + } + + public ValueNode memory() { + return memory; + } + + public ResolvedJavaType type() { + return type; + } + + @Override + public void lower(LoweringTool tool) { + tool.getRuntime().lower(this, tool); + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/NewArrayStubCall.java Mon Jul 09 14:22:22 2012 +0200 @@ -0,0 +1,85 @@ +/* + * Copyright (c) 2012, 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. + */ +package com.oracle.graal.hotspot.nodes; + +import static com.oracle.graal.hotspot.target.amd64.AMD64NewArrayStubCallOp.*; + +import com.oracle.graal.api.code.*; +import com.oracle.graal.api.meta.*; +import com.oracle.graal.compiler.gen.*; +import com.oracle.graal.compiler.target.*; +import com.oracle.graal.hotspot.*; +import com.oracle.graal.hotspot.target.amd64.*; +import com.oracle.graal.lir.*; +import com.oracle.graal.nodes.*; +import com.oracle.graal.nodes.type.*; + +/** + * Node implementing a call to HotSpot's {@code new_[object|type]_array} stub. + * + * @see AMD64NewArrayStubCallOp + */ +public class NewArrayStubCall extends FixedWithNextNode implements LIRGenLowerable { + + private static final Stamp defaultStamp = StampFactory.objectNonNull(); + + @Input private final ValueNode hub; + @Input private final ValueNode length; + private final boolean isObjectArray; + + public NewArrayStubCall(boolean isObjectArray, ValueNode hub, ValueNode length) { + super(defaultStamp); + this.isObjectArray = isObjectArray; + this.hub = hub; + this.length = length; + } + + @Override + public boolean inferStamp() { + if (stamp() == defaultStamp && hub.isConstant()) { + HotSpotKlassOop klassOop = (HotSpotKlassOop) this.hub.asConstant().asObject(); + updateStamp(StampFactory.exactNonNull(klassOop.type)); + return true; + } + return false; + } + + @Override + public void generate(LIRGenerator gen) { + RegisterValue hubFixed = HUB.asValue(Kind.Object); + RegisterValue lengthFixed = LENGTH.asValue(Kind.Int); + RegisterValue resultFixed = RESULT.asValue(Kind.Object); + gen.emitMove(gen.operand(length), lengthFixed); + gen.emitMove(gen.operand(hub), hubFixed); + LIRFrameState info = gen.state(); + gen.append(new AMD64NewArrayStubCallOp(isObjectArray, resultFixed, hubFixed, lengthFixed, info)); + Variable result = gen.emitMove(resultFixed); + gen.setResult(this, result); + } + + @SuppressWarnings("unused") + @NodeIntrinsic + public static Object call(@ConstantNodeParameter boolean isObjectArray, Object hub, int length) { + throw new UnsupportedOperationException(); + } +}
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/NewInstanceStubCall.java Mon Jul 09 14:15:55 2012 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/NewInstanceStubCall.java Mon Jul 09 14:22:22 2012 +0200 @@ -22,15 +22,17 @@ */ package com.oracle.graal.hotspot.nodes; +import static com.oracle.graal.hotspot.target.amd64.AMD64NewInstanceStubCallOp.*; + +import com.oracle.graal.api.code.*; import com.oracle.graal.api.meta.*; import com.oracle.graal.compiler.gen.*; import com.oracle.graal.compiler.target.*; import com.oracle.graal.hotspot.*; -import com.oracle.graal.hotspot.target.*; +import com.oracle.graal.hotspot.target.amd64.*; import com.oracle.graal.lir.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.type.*; -import com.oracle.max.asm.target.amd64.*; /** * Node implementing a call to HotSpot's {@code new_instance} stub. @@ -60,11 +62,12 @@ @Override public void generate(LIRGenerator gen) { - Variable result = gen.newVariable(Kind.Object); - gen.emitMove(gen.operand(hub), AMD64.rdx.asValue(Kind.Object)); + RegisterValue hubFixed = HUB.asValue(Kind.Object); + RegisterValue resultFixed = RESULT.asValue(Kind.Object); + gen.emitMove(gen.operand(hub), hubFixed); LIRFrameState info = gen.state(); - AMD64NewInstanceStubCallOp op = new AMD64NewInstanceStubCallOp(result, AMD64.rdx.asValue(Kind.Object), info); - gen.append(op); + gen.append(new AMD64NewInstanceStubCallOp(resultFixed, hubFixed, info)); + Variable result = gen.emitMove(resultFixed); gen.setResult(this, result); }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/TLABAllocateNode.java Mon Jul 09 14:15:55 2012 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/TLABAllocateNode.java Mon Jul 09 14:22:22 2012 +0200 @@ -22,6 +22,8 @@ */ package com.oracle.graal.hotspot.nodes; +import java.util.*; + import com.oracle.graal.api.meta.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.spi.*; @@ -35,27 +37,61 @@ public final class TLABAllocateNode extends FixedWithNextNode implements Lowerable { private final int size; + @Input private ValueNode sizeNode; public TLABAllocateNode(int size, Kind wordKind) { super(StampFactory.forWord(wordKind, true)); this.size = size; + this.sizeNode = null; + } + + public TLABAllocateNode(Kind wordKind, ValueNode size) { + super(StampFactory.forWord(wordKind, true)); + this.size = -1; + this.sizeNode = size; } - public int size() { + public boolean isSizeConstant() { + return sizeNode == null; + } + + public int constantSize() { + assert isSizeConstant(); return size; } + public ValueNode variableSize() { + assert !isSizeConstant(); + return sizeNode; + } + @Override public void lower(LoweringTool tool) { tool.getRuntime().lower(this, tool); } + @Override + public Map<Object, Object> getDebugProperties() { + Map<Object, Object> debugProperties = super.getDebugProperties(); + debugProperties.put("size", String.valueOf(size)); + return debugProperties; + } + /** * @return null if allocation fails */ @SuppressWarnings("unused") @NodeIntrinsic - public static Word allocate(@ConstantNodeParameter int size, @ConstantNodeParameter Kind wordKind) { + public static Word allocateConstantSize(@ConstantNodeParameter int size, @ConstantNodeParameter Kind wordKind) { + throw new UnsupportedOperationException(); + } + + /** + * @return null if allocation fails + */ + @SuppressWarnings("unused") + @NodeIntrinsic + public static Word allocateVariableSize(@ConstantNodeParameter Kind wordKind, int size) { throw new UnsupportedOperationException(); } }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/VerifyOopStubCall.java Mon Jul 09 14:15:55 2012 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/VerifyOopStubCall.java Mon Jul 09 14:22:22 2012 +0200 @@ -22,9 +22,13 @@ */ package com.oracle.graal.hotspot.nodes; +import static com.oracle.graal.hotspot.target.amd64.AMD64VerifyOopStubCallOp.*; + +import com.oracle.graal.api.code.*; +import com.oracle.graal.api.meta.*; import com.oracle.graal.compiler.gen.*; import com.oracle.graal.compiler.target.*; -import com.oracle.graal.hotspot.target.*; +import com.oracle.graal.hotspot.target.amd64.*; import com.oracle.graal.lir.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.type.*; @@ -45,9 +49,10 @@ @Override public void generate(LIRGenerator gen) { + RegisterValue objectFixed = OBJECT.asValue(Kind.Object); + gen.emitMove(gen.operand(object), objectFixed); LIRFrameState info = gen.state(); - AMD64VerifyOopStubCallOp op = new AMD64VerifyOopStubCallOp(gen.operand(object), info); - gen.append(op); + gen.append(new AMD64VerifyOopStubCallOp(gen.operand(object), info)); } @SuppressWarnings("unused")
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/snippets/ArrayCopySnippets.java Mon Jul 09 14:15:55 2012 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/snippets/ArrayCopySnippets.java Mon Jul 09 14:22:22 2012 +0200 @@ -30,6 +30,7 @@ import com.oracle.graal.snippets.*; import com.oracle.graal.snippets.Snippet.ConstantParameter; import com.oracle.graal.snippets.Snippet.Fold; +import com.oracle.graal.snippets.nodes.*; @SuppressWarnings("unused") @@ -312,12 +313,12 @@ if (src == dest && srcPos < destPos) { // bad aliased case for (long i = (length - 1) * scale; i >= 0; i -= scale) { Object a = UnsafeLoadNode.load(src, header, i + (long) srcPos * scale, Kind.Object); - DirectObjectStoreNode.store(dest, header, i + (long) destPos * scale, a); + DirectObjectStoreNode.storeObject(dest, header, i + (long) destPos * scale, a); } } else { for (long i = 0; i < length * scale; i += scale) { Object a = UnsafeLoadNode.load(src, header, i + (long) srcPos * scale, Kind.Object); - DirectObjectStoreNode.store(dest, header, i + (long) destPos * scale, a); + DirectObjectStoreNode.storeObject(dest, header, i + (long) destPos * scale, a); } } if (length > 0) {
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/snippets/CheckCastSnippets.java Mon Jul 09 14:15:55 2012 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/snippets/CheckCastSnippets.java Mon Jul 09 14:22:22 2012 +0200 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 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 @@ -22,15 +22,9 @@ */ package com.oracle.graal.hotspot.snippets; import static com.oracle.graal.hotspot.snippets.ArrayCopySnippets.*; -import static com.oracle.graal.hotspot.snippets.CheckCastSnippets.Counter.*; import static com.oracle.graal.snippets.Snippet.Multiple.*; import static com.oracle.graal.snippets.SnippetTemplate.Arguments.*; -import java.io.*; -import java.util.*; - -import sun.misc.*; - import com.oracle.graal.api.code.*; import com.oracle.graal.api.meta.*; import com.oracle.graal.compiler.*; @@ -174,7 +168,7 @@ for (int i = 0; i < secondarySupers.length; i++) { if (t == loadNonNullObjectElement(secondarySupers, i)) { - DirectObjectStoreNode.store(s, secondarySuperCacheOffset(), 0, t); + DirectObjectStoreNode.storeObject(s, secondarySuperCacheOffset(), 0, t); secondariesHit.inc(); return true; } @@ -214,7 +208,7 @@ Object[] secondarySupers = UnsafeCastNode.cast(UnsafeLoadNode.loadObject(s, 0, secondarySupersOffset(), true), Object[].class); for (int i = 0; i < secondarySupers.length; i++) { if (t == loadNonNullObjectElement(secondarySupers, i)) { - DirectObjectStoreNode.store(s, secondarySuperCacheOffset(), 0, t); + DirectObjectStoreNode.storeObject(s, secondarySuperCacheOffset(), 0, t); secondariesHit.inc(); return true; } @@ -224,54 +218,6 @@ return false; } - /** - * Counters for the various code paths through a checkcast. - */ - public enum Counter { - hintsHit("hit a hint type"), - exactHit("exact type test succeeded"), - exactMiss("exact type test failed"), - isNull("object tested was null"), - cacheHit("secondary type cache hit"), - secondariesHit("secondaries scan succeeded"), - secondariesMiss("secondaries scan failed"), - displayHit("primary type test succeeded"), - displayMiss("primary type test failed"), - T_equals_S("object type was equal to secondary type"); - - final String description; - final int index; - long count; - - private Counter(String desc) { - this.description = desc; - this.index = ordinal(); - } - - @Fold - static int countOffset() { - try { - return (int) Unsafe.getUnsafe().objectFieldOffset(Counter.class.getDeclaredField("count")); - } catch (Exception e) { - throw new GraalInternalError(e); - } - } - - /** - * Increments this counter if counters are enabled. The body of this method has been carefully crafted - * such that it contains no safepoints and no calls, neither of which are permissible in a snippet. - * Also, increments are not guaranteed to be atomic which is acceptable for a counter. - */ - void inc() { - if (ENABLED) { - DirectObjectStoreNode.store(this, countOffset(), 0, count + 1); - } - } - - static final Counter[] VALUES = values(); - static final boolean ENABLED = GraalOptions.CheckcastCounters; - } - @Fold private static int superCheckOffsetOffset() { return HotSpotGraalRuntime.getInstance().getConfig().superCheckOffsetOffset; @@ -292,41 +238,6 @@ return HotSpotGraalRuntime.getInstance().getConfig().hubOffset; } - public static void printCounter(PrintStream out, Counter c, long total) { - double percent = total == 0D ? 0D : ((double) (c.count * 100)) / total; - out.println(String.format("%16s: %5.2f%%%10d // %s", c.name(), percent, c.count, c.description)); - } - - public static void printCounters(PrintStream out) { - if (!Counter.ENABLED) { - return; - } - Counter[] counters = Counter.values(); - Arrays.sort(counters, new Comparator<Counter>() { - @Override - public int compare(Counter o1, Counter o2) { - if (o1.count > o2.count) { - return -1; - } else if (o2.count > o1.count) { - return 1; - } - return 0; - } - - }); - - long total = 0; - for (Counter c : counters) { - total += c.count; - } - - out.println(); - out.println("** Checkcast counters **"); - for (Counter c : counters) { - printCounter(out, c, total); - } - } - public static class Templates { private final Cache cache; @@ -393,4 +304,16 @@ return hintHubs; } } + + private static final SnippetCounter.Group counters = GraalOptions.SnippetCounters ? new SnippetCounter.Group("Checkcast") : null; + private static final SnippetCounter hintsHit = new SnippetCounter(counters, "hintsHit", "hit a hint type"); + private static final SnippetCounter exactHit = new SnippetCounter(counters, "exactHit", "exact type test succeeded"); + private static final SnippetCounter exactMiss = new SnippetCounter(counters, "exactMiss", "exact type test failed"); + private static final SnippetCounter isNull = new SnippetCounter(counters, "isNull", "object tested was null"); + private static final SnippetCounter cacheHit = new SnippetCounter(counters, "cacheHit", "secondary type cache hit"); + private static final SnippetCounter secondariesHit = new SnippetCounter(counters, "secondariesHit", "secondaries scan succeeded"); + private static final SnippetCounter secondariesMiss = new SnippetCounter(counters, "secondariesMiss", "secondaries scan failed"); + private static final SnippetCounter displayHit = new SnippetCounter(counters, "displayHit", "primary type test succeeded"); + private static final SnippetCounter displayMiss = new SnippetCounter(counters, "displayMiss", "primary type test failed"); + private static final SnippetCounter T_equals_S = new SnippetCounter(counters, "T_equals_S", "object type was equal to secondary type"); }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/snippets/DirectObjectStoreNode.java Mon Jul 09 14:15:55 2012 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,67 +0,0 @@ -/* - * Copyright (c) 2012, 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. - */ -package com.oracle.graal.hotspot.snippets; - -import com.oracle.graal.nodes.*; -import com.oracle.graal.nodes.extended.*; -import com.oracle.graal.nodes.spi.*; -import com.oracle.graal.nodes.type.*; - -/** - * A special purpose store node that differs from {@link UnsafeStoreNode} in that - * it is not a {@link StateSplit} and does not include a write barrier. - */ -class DirectObjectStoreNode extends FixedWithNextNode implements Lowerable { - @Input private ValueNode object; - @Input private ValueNode value; - @Input private ValueNode offset; - private final int displacement; - - public DirectObjectStoreNode(ValueNode object, int displacement, ValueNode offset, ValueNode value) { - super(StampFactory.forVoid()); - this.object = object; - this.value = value; - this.offset = offset; - this.displacement = displacement; - } - - @SuppressWarnings("unused") - @NodeIntrinsic - public static void store(Object obj, @ConstantNodeParameter int displacement, long offset, Object value) { - throw new UnsupportedOperationException(); - } - - @SuppressWarnings("unused") - @NodeIntrinsic - public static void store(Object obj, @ConstantNodeParameter int displacement, long offset, long value) { - throw new UnsupportedOperationException(); - } - - @Override - public void lower(LoweringTool tool) { - StructuredGraph graph = (StructuredGraph) this.graph(); - IndexedLocationNode location = IndexedLocationNode.create(LocationNode.ANY_LOCATION, value.kind(), displacement, offset, graph, false); - WriteNode write = graph.add(new WriteNode(object, value, location)); - graph.replaceFixedWithFixed(this, write); - } -}
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/snippets/NewInstanceSnippets.java Mon Jul 09 14:15:55 2012 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,229 +0,0 @@ -/* - * Copyright (c) 2012, 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. - */ -package com.oracle.graal.hotspot.snippets; - -import static com.oracle.graal.hotspot.nodes.CastFromHub.*; -import static com.oracle.graal.hotspot.nodes.RegisterNode.*; -import static com.oracle.graal.hotspot.snippets.DirectObjectStoreNode.*; -import static com.oracle.graal.nodes.extended.UnsafeLoadNode.*; -import static com.oracle.graal.snippets.SnippetTemplate.Arguments.*; -import static com.oracle.graal.snippets.nodes.ExplodeLoopNode.*; -import static com.oracle.max.asm.target.amd64.AMD64.*; - -import com.oracle.graal.api.code.*; -import com.oracle.graal.api.meta.*; -import com.oracle.graal.debug.*; -import com.oracle.graal.graph.*; -import com.oracle.graal.hotspot.*; -import com.oracle.graal.hotspot.meta.*; -import com.oracle.graal.hotspot.nodes.*; -import com.oracle.graal.nodes.*; -import com.oracle.graal.nodes.java.*; -import com.oracle.graal.nodes.spi.*; -import com.oracle.graal.snippets.*; -import com.oracle.graal.snippets.Snippet.ConstantParameter; -import com.oracle.graal.snippets.Snippet.Fold; -import com.oracle.graal.snippets.Snippet.Parameter; -import com.oracle.graal.snippets.SnippetTemplate.Arguments; -import com.oracle.graal.snippets.SnippetTemplate.Cache; -import com.oracle.graal.snippets.SnippetTemplate.Key; - -/** - * Snippets used for implementing NEW. - */ -public class NewInstanceSnippets implements SnippetsInterface { - - @Snippet - public static Word allocate(@ConstantParameter("size") int size) { - Word thread = asWord(register(r15, wordKind())); - Word top = loadWord(thread, threadTlabTopOffset()); - Word end = loadWord(thread, threadTlabEndOffset()); - Word newTop = top.plus(size); - if (newTop.belowOrEqual(end)) { - store(thread, 0, threadTlabTopOffset(), newTop); - return top; - } - return Word.zero(); - } - - @Snippet - public static Object initialize( - @Parameter("memory") Word memory, - @Parameter("hub") Object hub, - @Parameter("prototypeHeader") Word headerPrototype, - @ConstantParameter("size") int size) { - - if (memory == Word.zero()) { - return NewInstanceStubCall.call(hub); - } - formatObject(hub, size, memory, headerPrototype); - Object instance = memory.toObject(); - return castFromHub(verifyOop(instance), hub); - } - - private static Object verifyOop(Object object) { - if (verifyOops()) { - VerifyOopStubCall.call(object); - } - return object; - } - - private static Word asWord(Object object) { - return Word.fromObject(object); - } - - private static Word loadWord(Word address, int offset) { - Object value = loadObject(address, 0, offset, true); - return asWord(value); - } - - /** - * Maximum size of an object whose body is initialized by a sequence of - * zero-stores to its fields. Larger objects have their bodies initialized - * in a loop. - */ - private static final int MAX_UNROLLED_OBJECT_INITIALIZATION_SIZE = 10 * wordSize(); - - /** - * Formats some allocated memory with an object header zeroes out the rest. - */ - private static void formatObject(Object hub, int size, Word memory, Word headerPrototype) { - store(memory, 0, 0, headerPrototype); - store(memory, 0, hubOffset(), hub); - if (size <= MAX_UNROLLED_OBJECT_INITIALIZATION_SIZE) { - explodeLoop(); - for (int offset = 2 * wordSize(); offset < size; offset += wordSize()) { - store(memory, 0, offset, 0); - } - } else { - for (int offset = 2 * wordSize(); offset < size; offset += wordSize()) { - store(memory, 0, offset, 0); - } - } - } - - @Fold - private static boolean verifyOops() { - return HotSpotGraalRuntime.getInstance().getConfig().verifyOops; - } - - @Fold - private static int threadTlabTopOffset() { - return HotSpotGraalRuntime.getInstance().getConfig().threadTlabTopOffset; - } - - @Fold - private static int threadTlabEndOffset() { - return HotSpotGraalRuntime.getInstance().getConfig().threadTlabEndOffset; - } - - @Fold - private static Kind wordKind() { - return HotSpotGraalRuntime.getInstance().getTarget().wordKind; - } - - @Fold - private static int wordSize() { - return HotSpotGraalRuntime.getInstance().getTarget().wordSize; - } - - @Fold - private static int hubOffset() { - return HotSpotGraalRuntime.getInstance().getConfig().hubOffset; - } - - public static class Templates { - - private final Cache cache; - private final ResolvedJavaMethod allocate; - private final ResolvedJavaMethod initialize; - private final CodeCacheProvider runtime; - private final boolean useTLAB; - - public Templates(CodeCacheProvider runtime, boolean useTLAB) { - this.runtime = runtime; - this.cache = new Cache(runtime); - this.useTLAB = useTLAB; - try { - allocate = runtime.getResolvedJavaMethod(NewInstanceSnippets.class.getDeclaredMethod("allocate", int.class)); - initialize = runtime.getResolvedJavaMethod(NewInstanceSnippets.class.getDeclaredMethod("initialize", Word.class, Object.class, Word.class, int.class)); - } catch (NoSuchMethodException e) { - throw new GraalInternalError(e); - } - } - - /** - * Lowers a {@link NewInstanceNode}. - */ - @SuppressWarnings("unused") - public void lower(NewInstanceNode newInstanceNode, LoweringTool tool) { - StructuredGraph graph = (StructuredGraph) newInstanceNode.graph(); - HotSpotResolvedJavaType type = (HotSpotResolvedJavaType) newInstanceNode.instanceClass(); - HotSpotKlassOop hub = type.klassOop(); - int size = type.instanceSize(); - assert (size % wordSize()) == 0; - assert size >= 0; - - ValueNode memory; - if (!useTLAB) { - memory = ConstantNode.forObject(null, runtime, graph); - } else { - TLABAllocateNode tlabAllocateNode = graph.add(new TLABAllocateNode(size, wordKind())); - graph.addBeforeFixed(newInstanceNode, tlabAllocateNode); - memory = tlabAllocateNode; - } - InitializeNode initializeNode = graph.add(new InitializeNode(memory, type)); - graph.replaceFixedWithFixed(newInstanceNode, initializeNode); - } - - @SuppressWarnings("unused") - public void lower(TLABAllocateNode tlabAllocateNode, LoweringTool tool) { - StructuredGraph graph = (StructuredGraph) tlabAllocateNode.graph(); - int size = tlabAllocateNode.size(); - assert (size % wordSize()) == 0; - assert size >= 0; - Key key = new Key(allocate).add("size", size); - Arguments arguments = new Arguments(); - SnippetTemplate template = cache.get(key); - Debug.log("Lowering fastAllocate in %s: node=%s, template=%s, arguments=%s", graph, tlabAllocateNode, template, arguments); - template.instantiate(runtime, tlabAllocateNode, tlabAllocateNode, arguments); - } - - @SuppressWarnings("unused") - public void lower(InitializeNode initializeNode, LoweringTool tool) { - StructuredGraph graph = (StructuredGraph) initializeNode.graph(); - HotSpotResolvedJavaType type = (HotSpotResolvedJavaType) initializeNode.type(); - HotSpotKlassOop hub = type.klassOop(); - int size = type.instanceSize(); - assert (size % wordSize()) == 0; - assert size >= 0; - Key key = new Key(initialize).add("size", size); - ValueNode memory = initializeNode.memory(); - //assert memory instanceof AllocateNode || memory instanceof ConstantNode : memory; - Arguments arguments = arguments("memory", memory).add("hub", hub).add("prototypeHeader", type.prototypeHeader()); - SnippetTemplate template = cache.get(key); - Debug.log("Lowering initialize in %s: node=%s, template=%s, arguments=%s", graph, initializeNode, template, arguments); - template.instantiate(runtime, initializeNode, initializeNode, arguments); - } - } -}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/snippets/NewObjectSnippets.java Mon Jul 09 14:22:22 2012 +0200 @@ -0,0 +1,410 @@ +/* + * Copyright (c) 2012, 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. + */ +package com.oracle.graal.hotspot.snippets; + +import static com.oracle.graal.hotspot.nodes.CastFromHub.*; +import static com.oracle.graal.hotspot.nodes.RegisterNode.*; +import static com.oracle.graal.nodes.extended.UnsafeLoadNode.*; +import static com.oracle.graal.snippets.SnippetTemplate.Arguments.*; +import static com.oracle.graal.snippets.nodes.DirectObjectStoreNode.*; +import static com.oracle.graal.snippets.nodes.ExplodeLoopNode.*; +import static com.oracle.max.asm.target.amd64.AMD64.*; +import static com.oracle.max.criutils.UnsignedMath.*; + +import com.oracle.graal.api.code.*; +import com.oracle.graal.api.meta.*; +import com.oracle.graal.compiler.*; +import com.oracle.graal.debug.*; +import com.oracle.graal.graph.*; +import com.oracle.graal.hotspot.*; +import com.oracle.graal.hotspot.meta.*; +import com.oracle.graal.hotspot.nodes.*; +import com.oracle.graal.nodes.*; +import com.oracle.graal.nodes.java.*; +import com.oracle.graal.nodes.spi.*; +import com.oracle.graal.snippets.*; +import com.oracle.graal.snippets.Snippet.ConstantParameter; +import com.oracle.graal.snippets.Snippet.Fold; +import com.oracle.graal.snippets.Snippet.Parameter; +import com.oracle.graal.snippets.SnippetTemplate.Arguments; +import com.oracle.graal.snippets.SnippetTemplate.Cache; +import com.oracle.graal.snippets.SnippetTemplate.Key; + +/** + * Snippets used for implementing NEW, ANEWARRAY and NEWARRAY. + */ +public class NewObjectSnippets implements SnippetsInterface { + + @Snippet + public static Word allocate(@Parameter("size") int size) { + Word thread = asWord(register(r15, wordKind())); + Word top = loadWord(thread, threadTlabTopOffset()); + Word end = loadWord(thread, threadTlabEndOffset()); + Word newTop = top.plus(size); + if (newTop.belowOrEqual(end)) { + storeObject(thread, 0, threadTlabTopOffset(), newTop); + return top; + } + return Word.zero(); + } + + @Snippet + public static Object initializeObject( + @Parameter("memory") Word memory, + @Parameter("hub") Object hub, + @Parameter("initialMarkWord") Word initialMarkWord, + @ConstantParameter("size") int size) { + + if (memory == Word.zero()) { + new_stub.inc(); + return NewInstanceStubCall.call(hub); + } + formatObject(hub, size, memory, initialMarkWord); + Object instance = memory.toObject(); + return castFromHub(verifyOop(instance), hub); + } + + @Snippet + public static Object initializeObjectArray( + @Parameter("memory") Word memory, + @Parameter("hub") Object hub, + @Parameter("length") int length, + @Parameter("size") int size, + @Parameter("initialMarkWord") Word initialMarkWord, + @ConstantParameter("headerSize") int headerSize) { + return initializeArray(memory, hub, length, size, initialMarkWord, headerSize, true); + } + + @Snippet + public static Object initializePrimitiveArray( + @Parameter("memory") Word memory, + @Parameter("hub") Object hub, + @Parameter("length") int length, + @Parameter("size") int size, + @Parameter("initialMarkWord") Word initialMarkWord, + @ConstantParameter("headerSize") int headerSize) { + return initializeArray(memory, hub, length, size, initialMarkWord, headerSize, false); + } + + private static Object initializeArray(Word memory, Object hub, int length, int size, Word initialMarkWord, int headerSize, boolean isObjectArray) { + if (memory == Word.zero()) { + if (isObjectArray) { + anewarray_stub.inc(); + } else { + newarray_stub.inc(); + } + return NewArrayStubCall.call(isObjectArray, hub, length); + } + if (isObjectArray) { + anewarray_loopInit.inc(); + } else { + newarray_loopInit.inc(); + } + formatArray(hub, size, length, headerSize, memory, initialMarkWord); + Object instance = memory.toObject(); + return castFromHub(verifyOop(instance), hub); + } + + /** + * Maximum array length for which fast path allocation is used. + */ + private static final int MAX_ARRAY_FAST_PATH_ALLOCATION_LENGTH = 0x00FFFFFF; + + @Snippet + public static Object allocateArrayAndInitialize( + @Parameter("length") int length, + @ConstantParameter("alignment") int alignment, + @ConstantParameter("headerSize") int headerSize, + @ConstantParameter("log2ElementSize") int log2ElementSize, + @ConstantParameter("type") ResolvedJavaType type, + @ConstantParameter("wordKind") Kind wordKind) { + if (!belowThan(length, MAX_ARRAY_FAST_PATH_ALLOCATION_LENGTH)) { + // This handles both negative array sizes and very large array sizes + DeoptimizeNode.deopt(DeoptimizationAction.InvalidateReprofile, DeoptimizationReason.RuntimeConstraint); + } + int size = getArraySize(length, alignment, headerSize, log2ElementSize); + Word memory = TLABAllocateNode.allocateVariableSize(wordKind, size); + return InitializeArrayNode.initialize(memory, length, size, type); + } + + public static int getArraySize(int length, int alignment, int headerSize, int log2ElementSize) { + int size = (length << log2ElementSize) + headerSize + (alignment - 1); + int mask = ~(alignment - 1); + return size & mask; + } + + private static Object verifyOop(Object object) { + if (verifyOops()) { + VerifyOopStubCall.call(object); + } + return object; + } + + private static Word asWord(Object object) { + return Word.fromObject(object); + } + + private static Word loadWord(Word address, int offset) { + Object value = loadObject(address, 0, offset, true); + return asWord(value); + } + + /** + * Maximum size of an object whose body is initialized by a sequence of + * zero-stores to its fields. Larger objects have their bodies initialized + * in a loop. + */ + private static final int MAX_UNROLLED_OBJECT_ZEROING_SIZE = 10 * wordSize(); + + /** + * Formats some allocated memory with an object header zeroes out the rest. + */ + private static void formatObject(Object hub, int size, Word memory, Word headerPrototype) { + storeObject(memory, 0, markOffset(), headerPrototype); + storeObject(memory, 0, hubOffset(), hub); + if (size <= MAX_UNROLLED_OBJECT_ZEROING_SIZE) { + new_seqInit.inc(); + explodeLoop(); + for (int offset = 2 * wordSize(); offset < size; offset += wordSize()) { + storeWord(memory, 0, offset, Word.zero()); + } + } else { + new_loopInit.inc(); + for (int offset = 2 * wordSize(); offset < size; offset += wordSize()) { + storeWord(memory, 0, offset, Word.zero()); + } + } + } + + /** + * Formats some allocated memory with an object header zeroes out the rest. + */ + private static void formatArray(Object hub, int size, int length, int headerSize, Word memory, Word headerPrototype) { + storeObject(memory, 0, markOffset(), headerPrototype); + storeObject(memory, 0, hubOffset(), hub); + storeInt(memory, 0, arrayLengthOffset(), length); + for (int offset = headerSize; offset < size; offset += wordSize()) { + storeWord(memory, 0, offset, Word.zero()); + } + } + + public static class Templates { + + private final Cache cache; + private final ResolvedJavaMethod allocate; + private final ResolvedJavaMethod initializeObject; + private final ResolvedJavaMethod initializeObjectArray; + private final ResolvedJavaMethod initializePrimitiveArray; + private final ResolvedJavaMethod allocateArrayAndInitialize; + private final TargetDescription target; + private final CodeCacheProvider runtime; + private final boolean useTLAB; + + public Templates(CodeCacheProvider runtime, TargetDescription target, boolean useTLAB) { + this.runtime = runtime; + this.target = target; + this.cache = new Cache(runtime); + this.useTLAB = useTLAB; + try { + allocate = runtime.getResolvedJavaMethod(NewObjectSnippets.class.getDeclaredMethod("allocate", int.class)); + initializeObject = runtime.getResolvedJavaMethod(NewObjectSnippets.class.getDeclaredMethod("initializeObject", Word.class, Object.class, Word.class, int.class)); + initializeObjectArray = runtime.getResolvedJavaMethod(NewObjectSnippets.class.getDeclaredMethod("initializeObjectArray", Word.class, Object.class, int.class, int.class, Word.class, int.class)); + initializePrimitiveArray = runtime.getResolvedJavaMethod(NewObjectSnippets.class.getDeclaredMethod("initializePrimitiveArray", Word.class, Object.class, int.class, int.class, Word.class, int.class)); + allocateArrayAndInitialize = runtime.getResolvedJavaMethod(NewObjectSnippets.class.getDeclaredMethod("allocateArrayAndInitialize", int.class, int.class, int.class, int.class, ResolvedJavaType.class, Kind.class)); + } catch (NoSuchMethodException e) { + throw new GraalInternalError(e); + } + } + + /** + * Lowers a {@link NewInstanceNode}. + */ + @SuppressWarnings("unused") + public void lower(NewInstanceNode newInstanceNode, LoweringTool tool) { + StructuredGraph graph = (StructuredGraph) newInstanceNode.graph(); + HotSpotResolvedJavaType type = (HotSpotResolvedJavaType) newInstanceNode.instanceClass(); + HotSpotKlassOop hub = type.klassOop(); + int size = type.instanceSize(); + assert (size % wordSize()) == 0; + assert size >= 0; + + ValueNode memory; + if (!useTLAB) { + memory = ConstantNode.forConstant(new Constant(target.wordKind, 0L), runtime, graph); + } else { + TLABAllocateNode tlabAllocateNode = graph.add(new TLABAllocateNode(size, wordKind())); + graph.addBeforeFixed(newInstanceNode, tlabAllocateNode); + memory = tlabAllocateNode; + } + InitializeObjectNode initializeNode = graph.add(new InitializeObjectNode(memory, type)); + graph.replaceFixedWithFixed(newInstanceNode, initializeNode); + } + + /** + * Lowers a {@link NewArrayNode}. + */ + @SuppressWarnings("unused") + public void lower(NewArrayNode newArrayNode, LoweringTool tool) { + StructuredGraph graph = (StructuredGraph) newArrayNode.graph(); + ValueNode lengthNode = newArrayNode.length(); + TLABAllocateNode tlabAllocateNode; + ResolvedJavaType elementType = newArrayNode.elementType(); + ResolvedJavaType arrayType = elementType.arrayOf(); + Kind elementKind = elementType.kind(); + final int alignment = target.wordSize; + final int headerSize = elementKind.arrayBaseOffset(); + final Integer length = lengthNode.isConstant() ? Integer.valueOf(lengthNode.asConstant().asInt()) : null; + int log2ElementSize = CodeUtil.log2(target.sizeInBytes(elementKind)); + if (!useTLAB) { + ConstantNode zero = ConstantNode.forConstant(new Constant(target.wordKind, 0L), runtime, graph); + // value for 'size' doesn't matter as it isn't used since a stub call will be made anyway + // for both allocation and initialization - it just needs to be non-null + ConstantNode size = ConstantNode.forInt(-1, graph); + InitializeArrayNode initializeNode = graph.add(new InitializeArrayNode(zero, lengthNode, size, arrayType)); + graph.replaceFixedWithFixed(newArrayNode, initializeNode); + } else if (length != null && belowThan(length, MAX_ARRAY_FAST_PATH_ALLOCATION_LENGTH)) { + // Calculate aligned size + int size = getArraySize(length, alignment, headerSize, log2ElementSize); + ConstantNode sizeNode = ConstantNode.forInt(size, graph); + tlabAllocateNode = graph.add(new TLABAllocateNode(size, target.wordKind)); + graph.addBeforeFixed(newArrayNode, tlabAllocateNode); + InitializeArrayNode initializeNode = graph.add(new InitializeArrayNode(tlabAllocateNode, lengthNode, sizeNode, arrayType)); + graph.replaceFixedWithFixed(newArrayNode, initializeNode); + } else { + Key key = new Key(allocateArrayAndInitialize). + add("alignment", alignment). + add("headerSize", headerSize). + add("log2ElementSize", log2ElementSize). + add("wordKind", target.wordKind). + add("type", arrayType); + Arguments arguments = new Arguments().add("length", lengthNode); + SnippetTemplate template = cache.get(key); + Debug.log("Lowering allocateArrayAndInitialize in %s: node=%s, template=%s, arguments=%s", graph, newArrayNode, template, arguments); + template.instantiate(runtime, newArrayNode, newArrayNode, arguments); + } + } + + @SuppressWarnings("unused") + public void lower(TLABAllocateNode tlabAllocateNode, LoweringTool tool) { + StructuredGraph graph = (StructuredGraph) tlabAllocateNode.graph(); + ValueNode size; + if (tlabAllocateNode.isSizeConstant()) { + size = ConstantNode.forInt(tlabAllocateNode.constantSize(), graph); + } else { + size = tlabAllocateNode.variableSize(); + } + Key key = new Key(allocate); + Arguments arguments = arguments("size", size); + SnippetTemplate template = cache.get(key); + Debug.log("Lowering fastAllocate in %s: node=%s, template=%s, arguments=%s", graph, tlabAllocateNode, template, arguments); + template.instantiate(runtime, tlabAllocateNode, tlabAllocateNode, arguments); + } + + @SuppressWarnings("unused") + public void lower(InitializeObjectNode initializeNode, LoweringTool tool) { + StructuredGraph graph = (StructuredGraph) initializeNode.graph(); + HotSpotResolvedJavaType type = (HotSpotResolvedJavaType) initializeNode.type(); + assert !type.isArrayClass(); + HotSpotKlassOop hub = type.klassOop(); + int size = type.instanceSize(); + assert (size % wordSize()) == 0; + assert size >= 0; + Key key = new Key(initializeObject).add("size", size); + ValueNode memory = initializeNode.memory(); + Arguments arguments = arguments("memory", memory).add("hub", hub).add("initialMarkWord", type.initialMarkWord()); + SnippetTemplate template = cache.get(key); + Debug.log("Lowering initializeObject in %s: node=%s, template=%s, arguments=%s", graph, initializeNode, template, arguments); + template.instantiate(runtime, initializeNode, initializeNode, arguments); + } + + @SuppressWarnings("unused") + public void lower(InitializeArrayNode initializeNode, LoweringTool tool) { + StructuredGraph graph = (StructuredGraph) initializeNode.graph(); + HotSpotResolvedJavaType type = (HotSpotResolvedJavaType) initializeNode.type(); + ResolvedJavaType elementType = type.componentType(); + assert elementType != null; + HotSpotKlassOop hub = type.klassOop(); + Kind elementKind = elementType.kind(); + final int headerSize = elementKind.arrayBaseOffset(); + Key key = new Key(elementKind.isObject() ? initializeObjectArray : initializePrimitiveArray).add("headerSize", headerSize); + ValueNode memory = initializeNode.memory(); + Arguments arguments = arguments("memory", memory).add("hub", hub).add("initialMarkWord", type.initialMarkWord()).add("size", initializeNode.size()).add("length", initializeNode.length()); + SnippetTemplate template = cache.get(key); + Debug.log("Lowering initializeObjectArray in %s: node=%s, template=%s, arguments=%s", graph, initializeNode, template, arguments); + template.instantiate(runtime, initializeNode, initializeNode, arguments); + } + } + + @Fold + private static boolean verifyOops() { + return HotSpotGraalRuntime.getInstance().getConfig().verifyOops; + } + + @Fold + private static int threadTlabTopOffset() { + return HotSpotGraalRuntime.getInstance().getConfig().threadTlabTopOffset; + } + + @Fold + private static int threadTlabEndOffset() { + return HotSpotGraalRuntime.getInstance().getConfig().threadTlabEndOffset; + } + + @Fold + private static Kind wordKind() { + return HotSpotGraalRuntime.getInstance().getTarget().wordKind; + } + + @Fold + private static int wordSize() { + return HotSpotGraalRuntime.getInstance().getTarget().wordSize; + } + + @Fold + private static int markOffset() { + return HotSpotGraalRuntime.getInstance().getConfig().markOffset; + } + + @Fold + private static int hubOffset() { + return HotSpotGraalRuntime.getInstance().getConfig().hubOffset; + } + + @Fold + private static int arrayLengthOffset() { + return HotSpotGraalRuntime.getInstance().getConfig().arrayLengthOffset; + } + + private static final SnippetCounter.Group countersNew = GraalOptions.SnippetCounters ? new SnippetCounter.Group("NewInstance") : null; + private static final SnippetCounter new_seqInit = new SnippetCounter(countersNew, "tlabSeqInit", "TLAB alloc with unrolled zeroing"); + private static final SnippetCounter new_loopInit = new SnippetCounter(countersNew, "tlabLoopInit", "TLAB alloc with zeroing in a loop"); + private static final SnippetCounter new_stub = new SnippetCounter(countersNew, "stub", "alloc and zeroing via stub"); + + private static final SnippetCounter.Group countersNewPrimitiveArray = GraalOptions.SnippetCounters ? new SnippetCounter.Group("NewPrimitiveArray") : null; + private static final SnippetCounter newarray_loopInit = new SnippetCounter(countersNewPrimitiveArray, "tlabLoopInit", "TLAB alloc with zeroing in a loop"); + private static final SnippetCounter newarray_stub = new SnippetCounter(countersNewPrimitiveArray, "stub", "alloc and zeroing via stub"); + + private static final SnippetCounter.Group countersNewObjectArray = GraalOptions.SnippetCounters ? new SnippetCounter.Group("NewObjectArray") : null; + private static final SnippetCounter anewarray_loopInit = new SnippetCounter(countersNewObjectArray, "tlabLoopInit", "TLAB alloc with zeroing in a loop"); + private static final SnippetCounter anewarray_stub = new SnippetCounter(countersNewObjectArray, "stub", "alloc and zeroing via stub"); +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/snippets/UnsignedMathSnippets.java Mon Jul 09 14:22:22 2012 +0200 @@ -0,0 +1,86 @@ +/* + * Copyright (c) 2011, 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. + */ +package com.oracle.graal.hotspot.snippets; + +import static com.oracle.graal.nodes.MaterializeNode.*; +import static com.oracle.graal.nodes.calc.Condition.*; + +import com.oracle.graal.snippets.*; +import com.oracle.max.criutils.*; + +/** + * Snippets for {@link UnsignedMath}. + */ +@ClassSubstitution(UnsignedMath.class) +public class UnsignedMathSnippets implements SnippetsInterface { + + public static boolean aboveThan(int a, int b) { + return materialize(BT, b, a); + } + + public static boolean aboveOrEqual(int a, int b) { + return !materialize(BT, a, b); + } + + /** + * Unsigned comparison belowThan for two numbers. + */ + public static boolean belowThan(int a, int b) { + return materialize(BT, a, b); + } + + /** + * Unsigned comparison belowOrEqual for two numbers. + */ + public static boolean belowOrEqual(int a, int b) { + return !materialize(BT, b, a); + } + + /** + * Unsigned comparison aboveThan for two numbers. + */ + public static boolean aboveThan(long a, long b) { + return materialize(BT, b, a); + } + + /** + * Unsigned comparison aboveOrEqual for two numbers. + */ + public static boolean aboveOrEqual(long a, long b) { + return !materialize(BT, a, b); + } + + /** + * Unsigned comparison belowThan for two numbers. + */ + public static boolean belowThan(long a, long b) { + return materialize(BT, a, b); + } + + /** + * Unsigned comparison belowOrEqual for two numbers. + */ + public static boolean belowOrEqual(long a, long b) { + return !materialize(BT, b, a); + } +}
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/target/AMD64NewInstanceStubCallOp.java Mon Jul 09 14:15:55 2012 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,68 +0,0 @@ -/* - * Copyright (c) 2012, 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. - */ -package com.oracle.graal.hotspot.target; - -import static com.oracle.graal.api.code.ValueUtil.*; - -import com.oracle.graal.api.meta.*; -import com.oracle.graal.hotspot.*; -import com.oracle.graal.lir.*; -import com.oracle.graal.lir.amd64.*; -import com.oracle.graal.lir.asm.*; -import com.oracle.max.asm.target.amd64.*; -import com.oracle.graal.lir.LIRInstruction.Opcode; - -/** - * LIR instruction for calling HotSpot's {@code new_instance} stub. This stub is declared in c1_Runtime1.hpp - * and implemented in Runtime1::generate_code_for() which is located in c1_Runtime1_x86.cpp. - */ -@Opcode("NEW_INSTANCE") -public class AMD64NewInstanceStubCallOp extends AMD64LIRInstruction { - @Def protected Value result; - @Use protected Value hub; - @Temp protected Value temp; - @State protected LIRFrameState state; - - public AMD64NewInstanceStubCallOp(Value result, Value hub, LIRFrameState state) { - this.result = result; - this.hub = hub; - this.temp = AMD64.rax.asValue(Kind.Object); - this.state = state; - } - - @Override - public void emitCode(TargetMethodAssembler tasm, AMD64MacroAssembler masm) { - // rdx: (in) hub - // rax: (out) result - AMD64Call.directCall(tasm, masm, HotSpotGraalRuntime.getInstance().getConfig().newInstanceStub, state); - if (asRegister(result) != AMD64.rax) { - masm.movq(asRegister(result), AMD64.rax); - } - } - - @Override - protected void verify() { - super.verify(); - assert asRegister(hub) == AMD64.rdx; - } -}
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/target/AMD64VerifyOopStubCallOp.java Mon Jul 09 14:15:55 2012 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,60 +0,0 @@ -/* - * Copyright (c) 2012, 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. - */ -package com.oracle.graal.hotspot.target; - -import static com.oracle.graal.api.code.ValueUtil.*; - -import com.oracle.graal.api.meta.*; -import com.oracle.graal.hotspot.*; -import com.oracle.graal.lir.*; -import com.oracle.graal.lir.LIRInstruction.Opcode; -import com.oracle.graal.lir.amd64.*; -import com.oracle.graal.lir.asm.*; -import com.oracle.max.asm.target.amd64.*; - -/** - * A call to HotSpot's object pointer verification stub. - */ -@Opcode("VERIFY_OOP") -public class AMD64VerifyOopStubCallOp extends AMD64LIRInstruction { - @Use protected Value object; - @State protected LIRFrameState state; - - public AMD64VerifyOopStubCallOp(Value object, LIRFrameState state) { - this.object = object; - this.state = state; - } - - @Override - public void emitCode(TargetMethodAssembler tasm, AMD64MacroAssembler masm) { - // r13: (in) object - if (asRegister(object) != AMD64.r13) { - masm.push(AMD64.r13); - masm.movq(AMD64.r13, asRegister(object)); - } - AMD64Call.directCall(tasm, masm, HotSpotGraalRuntime.getInstance().getConfig().verifyOopStub, state); - if (asRegister(object) != AMD64.r13) { - masm.pop(AMD64.r13); - } - } -}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/target/amd64/AMD64NewArrayStubCallOp.java Mon Jul 09 14:22:22 2012 +0200 @@ -0,0 +1,98 @@ +/* + * Copyright (c) 2012, 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. + */ +package com.oracle.graal.hotspot.target.amd64; + +import static com.oracle.graal.api.code.ValueUtil.*; + +import com.oracle.graal.api.code.*; +import com.oracle.graal.api.meta.*; +import com.oracle.graal.hotspot.*; +import com.oracle.graal.lir.*; +import com.oracle.graal.lir.LIRInstruction.Opcode; +import com.oracle.graal.lir.amd64.*; +import com.oracle.graal.lir.asm.*; +import com.oracle.max.asm.target.amd64.*; + +/** + * LIR instruction for calling HotSpot's {@code new_[object|type]_array} stub. This stub is declared in c1_Runtime1.hpp + * and implemented in Runtime1::generate_code_for() which is located in c1_Runtime1_x86.cpp. + */ +@Opcode("NEW_ARRAY") +public class AMD64NewArrayStubCallOp extends AMD64LIRInstruction { + + /** + * The stub places the result in RAX. + */ + public static final Register RESULT = AMD64.rax; + + /** + * The stub expects the hub in RDX. + */ + public static final Register HUB = AMD64.rdx; + + /** + * The stub expects the length in RBX. + */ + public static final Register LENGTH = AMD64.rbx; + + /** + * The stub uses RCX, RSI, and RDI as temps. + */ + public static final Register[] TEMPS = {AMD64.rcx, AMD64.rdi, AMD64.rsi}; + + private final boolean isObjectArray; + + @Def protected Value result; + @Use protected Value hub; + @Use protected Value length; + @Temp protected Value[] temps; + + @State protected LIRFrameState state; + + public AMD64NewArrayStubCallOp(boolean isObjectArray, Value result, Value hub, Value length, LIRFrameState state) { + this.isObjectArray = isObjectArray; + this.result = result; + this.hub = hub; + this.length = length; + this.temps = new Value[TEMPS.length]; + for (int i = 0; i < temps.length; i++) { + temps[i] = TEMPS[i].asValue(Kind.Long); + } + this.state = state; + } + + @Override + public void emitCode(TargetMethodAssembler tasm, AMD64MacroAssembler masm) { + HotSpotVMConfig config = HotSpotGraalRuntime.getInstance().getConfig(); + long stub = isObjectArray ? config.newObjectArrayStub : config.newTypeArrayStub; + AMD64Call.directCall(tasm, masm, stub, state); + } + + @Override + protected void verify() { + super.verify(); + assert asRegister(hub) == HUB : "stub expects hub in " + HUB; + assert asRegister(length) == LENGTH : "stub expect length in " + LENGTH; + assert asRegister(result) == RESULT : "stub places result in " + RESULT; + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/target/amd64/AMD64NewInstanceStubCallOp.java Mon Jul 09 14:22:22 2012 +0200 @@ -0,0 +1,74 @@ +/* + * Copyright (c) 2012, 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. + */ +package com.oracle.graal.hotspot.target.amd64; + +import static com.oracle.graal.api.code.ValueUtil.*; + +import com.oracle.graal.api.code.*; +import com.oracle.graal.api.meta.*; +import com.oracle.graal.hotspot.*; +import com.oracle.graal.lir.*; +import com.oracle.graal.lir.LIRInstruction.Opcode; +import com.oracle.graal.lir.amd64.*; +import com.oracle.graal.lir.asm.*; +import com.oracle.max.asm.target.amd64.*; + +/** + * LIR instruction for calling HotSpot's {@code new_instance} stub. This stub is declared in c1_Runtime1.hpp + * and implemented in Runtime1::generate_code_for() which is located in c1_Runtime1_x86.cpp. + */ +@Opcode("NEW_INSTANCE") +public class AMD64NewInstanceStubCallOp extends AMD64LIRInstruction { + + /** + * The stub expects the hub in RDX. + */ + public static final Register HUB = AMD64.rdx; + + /** + * The stub places the result in RAX. + */ + public static final Register RESULT = AMD64.rax; + + @Def protected Value result; + @Use protected Value hub; + @State protected LIRFrameState state; + + public AMD64NewInstanceStubCallOp(Value result, Value hub, LIRFrameState state) { + this.hub = hub; + this.result = result; + this.state = state; + } + + @Override + public void emitCode(TargetMethodAssembler tasm, AMD64MacroAssembler masm) { + AMD64Call.directCall(tasm, masm, HotSpotGraalRuntime.getInstance().getConfig().newInstanceStub, state); + } + + @Override + protected void verify() { + super.verify(); + assert asRegister(hub) == HUB : "expects hub in " + HUB; + assert asRegister(result) == RESULT : "expects result in " + RESULT; + } +}
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/target/amd64/AMD64TailcallOp.java Mon Jul 09 14:15:55 2012 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/target/amd64/AMD64TailcallOp.java Mon Jul 09 14:22:22 2012 +0200 @@ -33,7 +33,7 @@ import com.oracle.max.asm.target.amd64.*; /** - * Performs a hard-coded tail call to the specified target, which normally should be an RiCompiledCode instance. + * Performs a hard-coded tail call to the specified target, which normally should be an {@link InstalledCode} instance. */ @Opcode("TAILCALL") public class AMD64TailcallOp extends AMD64LIRInstruction {
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/target/amd64/AMD64VerifyOopStubCallOp.java Mon Jul 09 14:22:22 2012 +0200 @@ -0,0 +1,65 @@ +/* + * Copyright (c) 2012, 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. + */ +package com.oracle.graal.hotspot.target.amd64; + +import static com.oracle.graal.api.code.ValueUtil.*; + +import com.oracle.graal.api.code.*; +import com.oracle.graal.api.meta.*; +import com.oracle.graal.hotspot.*; +import com.oracle.graal.lir.*; +import com.oracle.graal.lir.LIRInstruction.Opcode; +import com.oracle.graal.lir.amd64.*; +import com.oracle.graal.lir.asm.*; +import com.oracle.max.asm.target.amd64.*; + +/** + * A call to HotSpot's object pointer verification stub. + */ +@Opcode("VERIFY_OOP") +public class AMD64VerifyOopStubCallOp extends AMD64LIRInstruction { + + /** + * The stub expects the object pointer in R13. + */ + public static final Register OBJECT = AMD64.r13; + + @Use protected Value object; + @State protected LIRFrameState state; + + public AMD64VerifyOopStubCallOp(Value object, LIRFrameState state) { + this.object = object; + this.state = state; + } + + @Override + public void emitCode(TargetMethodAssembler tasm, AMD64MacroAssembler masm) { + AMD64Call.directCall(tasm, masm, HotSpotGraalRuntime.getInstance().getConfig().verifyOopStub, state); + } + + @Override + protected void verify() { + super.verify(); + assert asRegister(object) == OBJECT : "expects object in " + OBJECT; + } +}
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/target/amd64/HotSpotAMD64Backend.java Mon Jul 09 14:15:55 2012 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/target/amd64/HotSpotAMD64Backend.java Mon Jul 09 14:22:22 2012 +0200 @@ -56,7 +56,7 @@ } @Override - public LIRGenerator newLIRGenerator(Graph graph, FrameMap frameMap, ResolvedJavaMethod method, LIR lir, RiXirGenerator xir, Assumptions assumptions) { + public LIRGenerator newLIRGenerator(Graph graph, FrameMap frameMap, ResolvedJavaMethod method, LIR lir, XirGenerator xir, Assumptions assumptions) { return new AMD64LIRGenerator(graph, runtime, target, frameMap, method, lir, xir, assumptions) { @Override
--- a/graal/com.oracle.graal.interpreter/src/com/oracle/graal/interpreter/BytecodeInterpreter.java Mon Jul 09 14:15:55 2012 +0200 +++ b/graal/com.oracle.graal.interpreter/src/com/oracle/graal/interpreter/BytecodeInterpreter.java Mon Jul 09 14:22:22 2012 +0200 @@ -31,17 +31,8 @@ import com.oracle.graal.bytecode.*; /** - * - * <h1>Implementation notes</h1> - * <li>Native methods are invoked using standard java reflection.</li> - * - * <h1>Features:</h1> - * - * - * <h1>Limitations:</h1> - * - * <li>The interpreter is not able to recognize a native method that calls a java method. - * In that case the java method will be interpreted directly on the vm interpreter.</li> + * High-level bytecode interpreter that executes on top of Java. Java native methods + * are executed using the {@link com.oracle.graal.api.interpreter.RuntimeInterpreterInterface}. */ @SuppressWarnings("static-method") public final class BytecodeInterpreter implements Interpreter { @@ -62,7 +53,6 @@ private Map<ResolvedJavaMethod, MethodRedirectionInfo> methodDelegates; private int maxStackFrames; - private int stackFrameDepth; private ResolvedJavaMethod rootMethod; private RuntimeInterpreterInterface runtimeInterface; @@ -95,36 +85,39 @@ } private void registerDelegates() { - addDelegate(findMethod(Throwable.class, "fillInStackTrace"), new InterpreterCallable() { - @Override - public Object invoke(InterpreterFrame caller, ResolvedJavaMethod method, Object[] arguments) throws Throwable { - setBackTrace(caller, (Throwable) arguments[0], createStackTraceElements(caller)); - return null; - } - }); - addDelegate(findMethod(Throwable.class, "getStackTraceDepth"), new InterpreterCallable() { - @Override - public Object invoke(InterpreterFrame caller, ResolvedJavaMethod method, Object[] arguments) throws Throwable { - StackTraceElement[] elements = getBackTrace(caller, (Throwable) arguments[0]); - if (elements != null) { - return elements.length; - } - return 0; - } - }); - addDelegate(findMethod(Throwable.class, "getStackTraceElement", int.class), new InterpreterCallable() { - @Override - public Object invoke(InterpreterFrame caller, ResolvedJavaMethod method, Object[] arguments) throws Throwable { - StackTraceElement[] elements = getBackTrace(caller, (Throwable) arguments[0]); - if (elements != null) { - Integer index = (Integer) arguments[0]; - if (index != null) { - return elements[index]; - } - } - return null; - } - }); + addDelegate(findMethod(Throwable.class, "fillInStackTrace"), new InterpreterCallable() { + + @Override + public Object invoke(InterpreterFrame caller, ResolvedJavaMethod method, Object[] arguments) throws Throwable { + setBackTrace(caller, (Throwable) arguments[0], createStackTraceElements(caller)); + return null; + } + }); + addDelegate(findMethod(Throwable.class, "getStackTraceDepth"), new InterpreterCallable() { + + @Override + public Object invoke(InterpreterFrame caller, ResolvedJavaMethod method, Object[] arguments) throws Throwable { + StackTraceElement[] elements = getBackTrace(caller, (Throwable) arguments[0]); + if (elements != null) { + return elements.length; + } + return 0; + } + }); + addDelegate(findMethod(Throwable.class, "getStackTraceElement", int.class), new InterpreterCallable() { + + @Override + public Object invoke(InterpreterFrame caller, ResolvedJavaMethod method, Object[] arguments) throws Throwable { + StackTraceElement[] elements = getBackTrace(caller, (Throwable) arguments[0]); + if (elements != null) { + Integer index = (Integer) arguments[0]; + if (index != null) { + return elements[index]; + } + } + return null; + } + }); } @SuppressWarnings("unused") @@ -162,6 +155,10 @@ assert boxedArguments != null; assert signature.argumentCount(receiver) == boxedArguments.length; + if (TRACE) { + trace(0, "Executing root method " + method); + } + InterpreterFrame rootFrame = new InterpreterFrame(rootMethod, signature.argumentSlots(true)); rootFrame.pushObject(this); rootFrame.pushObject(method); @@ -173,7 +170,7 @@ index++; } - for (int i = 0; i < boxedArguments.length; i++, index++) { + for (int i = 0; index < boxedArguments.length; i++, index++) { pushAsObject(rootFrame, signature.argumentKindAt(i), boxedArguments[index]); } @@ -181,6 +178,7 @@ executeRoot(rootFrame, frame); return popAsObject(rootFrame, signature.returnKind()); } catch (Exception e) { + // TODO (chaeubl): remove this exception handler (only used for debugging) throw e; } } @@ -194,9 +192,7 @@ } private void executeRoot(InterpreterFrame root, InterpreterFrame frame) throws Throwable { - //TODO reflection redirection - stackFrameDepth = 0; - + // TODO reflection redirection InterpreterFrame prevFrame = frame; InterpreterFrame currentFrame = frame; BytecodeStream bs = new BytecodeStream(currentFrame.getMethod().code()); @@ -220,17 +216,17 @@ while (true) { int result = executeInstruction(frame, bs); switch (result) { - case NEXT : + case NEXT: bs.next(); break; - case RETURN : + case RETURN: return popFrame(frame); case CALL: return allocateFrame(frame, bs); - case BRANCH : + case BRANCH: bs.setBCI(bs.readBranchDest()); break; - default : + default: // the outcome depends on stack values assert result >= 0 : "negative branch target"; bs.setBCI(result); @@ -239,7 +235,7 @@ } } catch (Throwable t) { if (TRACE) { - traceOp("Exception " + t.toString()); + traceOp(frame, "Exception " + t.toString()); } updateStackTrace(frame, t); @@ -252,7 +248,7 @@ throw t; } else { if (TRACE) { - traceOp("Handler found " + handlerFrame.getMethod() + ":" + handlerFrame.getBCI()); + traceOp(frame, "Handler found " + handlerFrame.getMethod() + ":" + handlerFrame.getBCI()); } // update bci from frame bs.setBCI(handlerFrame.getBCI()); @@ -268,79 +264,80 @@ private int executeInstruction(InterpreterFrame frame, BytecodeStream bs) throws Throwable { if (TRACE_BYTE_CODE) { - traceOp(bs.currentBCI() + ": " + Bytecodes.baseNameOf(bs.currentBC())); + traceOp(frame, bs.currentBCI() + ": " + Bytecodes.baseNameOf(bs.currentBC())); } - switch(bs.currentBC()) { - case Bytecodes.NOP : break; - case Bytecodes.ACONST_NULL : + switch (bs.currentBC()) { + case Bytecodes.NOP: + break; + case Bytecodes.ACONST_NULL: frame.pushObject(null); break; - case Bytecodes.ICONST_M1 : + case Bytecodes.ICONST_M1: frame.pushInt(-1); break; - case Bytecodes.ICONST_0 : + case Bytecodes.ICONST_0: frame.pushInt(0); break; - case Bytecodes.ICONST_1 : + case Bytecodes.ICONST_1: frame.pushInt(1); break; - case Bytecodes.ICONST_2 : + case Bytecodes.ICONST_2: frame.pushInt(2); break; - case Bytecodes.ICONST_3 : + case Bytecodes.ICONST_3: frame.pushInt(3); break; - case Bytecodes.ICONST_4 : + case Bytecodes.ICONST_4: frame.pushInt(4); break; - case Bytecodes.ICONST_5 : + case Bytecodes.ICONST_5: frame.pushInt(5); break; - case Bytecodes.LCONST_0 : + case Bytecodes.LCONST_0: frame.pushLong(0L); break; - case Bytecodes.LCONST_1 : + case Bytecodes.LCONST_1: frame.pushLong(1L); break; - case Bytecodes.FCONST_0 : + case Bytecodes.FCONST_0: frame.pushFloat(0.0F); break; - case Bytecodes.FCONST_1 : + case Bytecodes.FCONST_1: frame.pushFloat(1.0F); break; - case Bytecodes.FCONST_2 : + case Bytecodes.FCONST_2: frame.pushFloat(2.0F); break; - case Bytecodes.DCONST_0 : + case Bytecodes.DCONST_0: frame.pushDouble(0.0D); break; - case Bytecodes.DCONST_1 : + case Bytecodes.DCONST_1: frame.pushDouble(1.0D); break; - case Bytecodes.BIPUSH : + case Bytecodes.BIPUSH: frame.pushInt(bs.readByte()); break; - case Bytecodes.SIPUSH : + case Bytecodes.SIPUSH: frame.pushInt(bs.readShort()); break; - case Bytecodes.LDC : - case Bytecodes.LDC_W : - case Bytecodes.LDC2_W : + case Bytecodes.LDC: + case Bytecodes.LDC_W: + case Bytecodes.LDC2_W: pushCPConstant(frame, bs.readCPI()); break; - case Bytecodes.ILOAD : + case Bytecodes.ILOAD: frame.pushInt(frame.getInt(frame.resolveLocalIndex(bs.readLocalIndex()))); break; - case Bytecodes.LLOAD : + case Bytecodes.LLOAD: frame.pushLong(frame.getLong(frame.resolveLocalIndex(bs.readLocalIndex()))); break; - case Bytecodes.FLOAD : + case Bytecodes.FLOAD: frame.pushFloat(frame.getFloat(frame.resolveLocalIndex(bs.readLocalIndex()))); break; - case Bytecodes.DLOAD : + case Bytecodes.DLOAD: frame.pushDouble(frame.getDouble(frame.resolveLocalIndex(bs.readLocalIndex()))); break; - case Bytecodes.ALOAD : + case Bytecodes.ALOAD: frame.pushObject(frame.getObject(frame.resolveLocalIndex(bs.readLocalIndex()))); break; case Bytecodes.ILOAD_0: @@ -355,441 +352,441 @@ case Bytecodes.ILOAD_3: frame.pushInt(frame.getInt(frame.resolveLocalIndex(3))); break; - case Bytecodes.LLOAD_0 : + case Bytecodes.LLOAD_0: frame.pushLong(frame.getLong(frame.resolveLocalIndex(0))); break; - case Bytecodes.LLOAD_1 : + case Bytecodes.LLOAD_1: frame.pushLong(frame.getLong(frame.resolveLocalIndex(1))); break; - case Bytecodes.LLOAD_2 : + case Bytecodes.LLOAD_2: frame.pushLong(frame.getLong(frame.resolveLocalIndex(2))); break; - case Bytecodes.LLOAD_3 : + case Bytecodes.LLOAD_3: frame.pushLong(frame.getLong(frame.resolveLocalIndex(3))); break; - case Bytecodes.FLOAD_0 : + case Bytecodes.FLOAD_0: frame.pushFloat(frame.getFloat(frame.resolveLocalIndex(0))); break; - case Bytecodes.FLOAD_1 : + case Bytecodes.FLOAD_1: frame.pushFloat(frame.getFloat(frame.resolveLocalIndex(1))); break; - case Bytecodes.FLOAD_2 : + case Bytecodes.FLOAD_2: frame.pushFloat(frame.getFloat(frame.resolveLocalIndex(2))); break; - case Bytecodes.FLOAD_3 : + case Bytecodes.FLOAD_3: frame.pushFloat(frame.getFloat(frame.resolveLocalIndex(3))); break; - case Bytecodes.DLOAD_0 : + case Bytecodes.DLOAD_0: frame.pushDouble(frame.getDouble(frame.resolveLocalIndex(0))); break; - case Bytecodes.DLOAD_1 : + case Bytecodes.DLOAD_1: frame.pushDouble(frame.getDouble(frame.resolveLocalIndex(1))); break; - case Bytecodes.DLOAD_2 : + case Bytecodes.DLOAD_2: frame.pushDouble(frame.getDouble(frame.resolveLocalIndex(2))); break; - case Bytecodes.DLOAD_3 : + case Bytecodes.DLOAD_3: frame.pushDouble(frame.getDouble(frame.resolveLocalIndex(3))); break; - case Bytecodes.ALOAD_0 : + case Bytecodes.ALOAD_0: frame.pushObject(frame.getObject(frame.resolveLocalIndex(0))); break; - case Bytecodes.ALOAD_1 : + case Bytecodes.ALOAD_1: frame.pushObject(frame.getObject(frame.resolveLocalIndex(1))); break; - case Bytecodes.ALOAD_2 : + case Bytecodes.ALOAD_2: frame.pushObject(frame.getObject(frame.resolveLocalIndex(2))); break; - case Bytecodes.ALOAD_3 : + case Bytecodes.ALOAD_3: frame.pushObject(frame.getObject(frame.resolveLocalIndex(3))); break; - case Bytecodes.IALOAD : + case Bytecodes.IALOAD: frame.pushInt(runtimeInterface.getArrayInt(frame.popInt(), frame.popObject())); break; - case Bytecodes.LALOAD : + case Bytecodes.LALOAD: frame.pushLong(runtimeInterface.getArrayLong(frame.popInt(), frame.popObject())); break; - case Bytecodes.FALOAD : + case Bytecodes.FALOAD: frame.pushFloat(runtimeInterface.getArrayFloat(frame.popInt(), frame.popObject())); break; - case Bytecodes.DALOAD : + case Bytecodes.DALOAD: frame.pushDouble(runtimeInterface.getArrayDouble(frame.popInt(), frame.popObject())); break; - case Bytecodes.AALOAD : + case Bytecodes.AALOAD: frame.pushObject(runtimeInterface.getArrayObject(frame.popInt(), frame.popObject())); break; - case Bytecodes.BALOAD : + case Bytecodes.BALOAD: frame.pushInt(runtimeInterface.getArrayByte(frame.popInt(), frame.popObject())); break; - case Bytecodes.CALOAD : + case Bytecodes.CALOAD: frame.pushInt(runtimeInterface.getArrayChar(frame.popInt(), frame.popObject())); break; - case Bytecodes.SALOAD: + case Bytecodes.SALOAD: frame.pushInt(runtimeInterface.getArrayShort(frame.popInt(), frame.popObject())); break; case Bytecodes.ISTORE: frame.setInt(frame.resolveLocalIndex(bs.readLocalIndex()), frame.popInt()); break; - case Bytecodes.LSTORE : + case Bytecodes.LSTORE: frame.setLong(frame.resolveLocalIndex(bs.readLocalIndex()), frame.popLong()); break; - case Bytecodes.FSTORE : + case Bytecodes.FSTORE: frame.setFloat(frame.resolveLocalIndex(bs.readLocalIndex()), frame.popFloat()); break; - case Bytecodes.DSTORE : + case Bytecodes.DSTORE: frame.setDouble(frame.resolveLocalIndex(bs.readLocalIndex()), frame.popDouble()); break; - case Bytecodes.ASTORE : + case Bytecodes.ASTORE: frame.setObject(frame.resolveLocalIndex(bs.readLocalIndex()), frame.popObject()); break; - case Bytecodes.ISTORE_0 : + case Bytecodes.ISTORE_0: frame.setInt(frame.resolveLocalIndex(0), frame.popInt()); break; - case Bytecodes.ISTORE_1 : + case Bytecodes.ISTORE_1: frame.setInt(frame.resolveLocalIndex(1), frame.popInt()); break; - case Bytecodes.ISTORE_2 : + case Bytecodes.ISTORE_2: frame.setInt(frame.resolveLocalIndex(2), frame.popInt()); break; - case Bytecodes.ISTORE_3 : + case Bytecodes.ISTORE_3: frame.setInt(frame.resolveLocalIndex(3), frame.popInt()); break; - case Bytecodes.LSTORE_0 : + case Bytecodes.LSTORE_0: frame.setLong(frame.resolveLocalIndex(0), frame.popLong()); break; - case Bytecodes.LSTORE_1 : + case Bytecodes.LSTORE_1: frame.setLong(frame.resolveLocalIndex(1), frame.popLong()); break; - case Bytecodes.LSTORE_2 : + case Bytecodes.LSTORE_2: frame.setLong(frame.resolveLocalIndex(2), frame.popLong()); break; - case Bytecodes.LSTORE_3 : + case Bytecodes.LSTORE_3: frame.setLong(frame.resolveLocalIndex(3), frame.popLong()); break; - case Bytecodes.FSTORE_0 : + case Bytecodes.FSTORE_0: frame.setFloat(frame.resolveLocalIndex(0), frame.popFloat()); break; - case Bytecodes.FSTORE_1 : + case Bytecodes.FSTORE_1: frame.setFloat(frame.resolveLocalIndex(1), frame.popFloat()); break; - case Bytecodes.FSTORE_2 : + case Bytecodes.FSTORE_2: frame.setFloat(frame.resolveLocalIndex(2), frame.popFloat()); break; - case Bytecodes.FSTORE_3 : + case Bytecodes.FSTORE_3: frame.setFloat(frame.resolveLocalIndex(3), frame.popFloat()); break; - case Bytecodes.DSTORE_0 : + case Bytecodes.DSTORE_0: frame.setDouble(frame.resolveLocalIndex(0), frame.popDouble()); break; - case Bytecodes.DSTORE_1 : + case Bytecodes.DSTORE_1: frame.setDouble(frame.resolveLocalIndex(1), frame.popDouble()); break; - case Bytecodes.DSTORE_2 : + case Bytecodes.DSTORE_2: frame.setDouble(frame.resolveLocalIndex(2), frame.popDouble()); break; - case Bytecodes.DSTORE_3 : + case Bytecodes.DSTORE_3: frame.setDouble(frame.resolveLocalIndex(3), frame.popDouble()); break; - case Bytecodes.ASTORE_0 : + case Bytecodes.ASTORE_0: frame.setObject(frame.resolveLocalIndex(0), frame.popObject()); break; - case Bytecodes.ASTORE_1 : + case Bytecodes.ASTORE_1: frame.setObject(frame.resolveLocalIndex(1), frame.popObject()); break; - case Bytecodes.ASTORE_2 : + case Bytecodes.ASTORE_2: frame.setObject(frame.resolveLocalIndex(2), frame.popObject()); break; - case Bytecodes.ASTORE_3 : + case Bytecodes.ASTORE_3: frame.setObject(frame.resolveLocalIndex(3), frame.popObject()); break; - case Bytecodes.IASTORE : + case Bytecodes.IASTORE: runtimeInterface.setArrayInt(frame.popInt(), frame.popInt(), frame.popObject()); break; - case Bytecodes.LASTORE : + case Bytecodes.LASTORE: runtimeInterface.setArrayLong(frame.popLong(), frame.popInt(), frame.popObject()); break; - case Bytecodes.FASTORE : + case Bytecodes.FASTORE: runtimeInterface.setArrayFloat(frame.popFloat(), frame.popInt(), frame.popObject()); break; - case Bytecodes.DASTORE : + case Bytecodes.DASTORE: runtimeInterface.setArrayDouble(frame.popDouble(), frame.popInt(), frame.popObject()); break; - case Bytecodes.AASTORE : + case Bytecodes.AASTORE: runtimeInterface.setArrayObject(frame.popObject(), frame.popInt(), frame.popObject()); break; - case Bytecodes.BASTORE : + case Bytecodes.BASTORE: runtimeInterface.setArrayByte((byte) frame.popInt(), frame.popInt(), frame.popObject()); break; - case Bytecodes.CASTORE : + case Bytecodes.CASTORE: runtimeInterface.setArrayChar((char) frame.popInt(), frame.popInt(), frame.popObject()); break; - case Bytecodes.SASTORE : + case Bytecodes.SASTORE: runtimeInterface.setArrayShort((short) frame.popInt(), frame.popInt(), frame.popObject()); break; - case Bytecodes.POP : + case Bytecodes.POP: frame.popVoid(1); break; - case Bytecodes.POP2 : + case Bytecodes.POP2: frame.popVoid(2); break; - case Bytecodes.DUP : + case Bytecodes.DUP: frame.dup(1); break; - case Bytecodes.DUP_X1 : + case Bytecodes.DUP_X1: frame.dupx1(); break; - case Bytecodes.DUP_X2 : + case Bytecodes.DUP_X2: frame.dupx2(); break; - case Bytecodes.DUP2 : + case Bytecodes.DUP2: frame.dup(2); break; - case Bytecodes.DUP2_X1 : + case Bytecodes.DUP2_X1: frame.dup2x1(); break; - case Bytecodes.DUP2_X2 : + case Bytecodes.DUP2_X2: frame.dup2x2(); break; - case Bytecodes.SWAP : + case Bytecodes.SWAP: frame.swapSingle(); break; - case Bytecodes.IADD : + case Bytecodes.IADD: frame.pushInt(frame.popInt() + frame.popInt()); break; - case Bytecodes.LADD : + case Bytecodes.LADD: frame.pushLong(frame.popLong() + frame.popLong()); break; - case Bytecodes.FADD : + case Bytecodes.FADD: frame.pushFloat(frame.popFloat() + frame.popFloat()); break; - case Bytecodes.DADD : + case Bytecodes.DADD: frame.pushDouble(frame.popDouble() + frame.popDouble()); break; - case Bytecodes.ISUB : + case Bytecodes.ISUB: frame.pushInt(-frame.popInt() + frame.popInt()); break; - case Bytecodes.LSUB : + case Bytecodes.LSUB: frame.pushLong(-frame.popLong() + frame.popLong()); break; - case Bytecodes.FSUB : + case Bytecodes.FSUB: frame.pushFloat(-frame.popFloat() + frame.popFloat()); break; - case Bytecodes.DSUB : + case Bytecodes.DSUB: frame.pushDouble(-frame.popDouble() + frame.popDouble()); break; - case Bytecodes.IMUL : + case Bytecodes.IMUL: frame.pushInt(frame.popInt() * frame.popInt()); break; - case Bytecodes.LMUL : + case Bytecodes.LMUL: frame.pushLong(frame.popLong() * frame.popLong()); break; - case Bytecodes.FMUL : + case Bytecodes.FMUL: frame.pushFloat(frame.popFloat() * frame.popFloat()); break; - case Bytecodes.DMUL : + case Bytecodes.DMUL: frame.pushDouble(frame.popDouble() * frame.popDouble()); break; - case Bytecodes.IDIV : + case Bytecodes.IDIV: divInt(frame); break; - case Bytecodes.LDIV : + case Bytecodes.LDIV: divLong(frame); break; - case Bytecodes.FDIV : + case Bytecodes.FDIV: divFloat(frame); break; - case Bytecodes.DDIV : + case Bytecodes.DDIV: divDouble(frame); break; - case Bytecodes.IREM : + case Bytecodes.IREM: remInt(frame); break; - case Bytecodes.LREM : + case Bytecodes.LREM: remLong(frame); break; - case Bytecodes.FREM : + case Bytecodes.FREM: remFloat(frame); break; - case Bytecodes.DREM : + case Bytecodes.DREM: remDouble(frame); break; - case Bytecodes.INEG : + case Bytecodes.INEG: frame.pushInt(-frame.popInt()); break; - case Bytecodes.LNEG : + case Bytecodes.LNEG: frame.pushLong(-frame.popLong()); break; - case Bytecodes.FNEG : + case Bytecodes.FNEG: frame.pushFloat(-frame.popFloat()); break; - case Bytecodes.DNEG : + case Bytecodes.DNEG: frame.pushDouble(-frame.popDouble()); break; - case Bytecodes.ISHL : + case Bytecodes.ISHL: shiftLeftInt(frame); break; - case Bytecodes.LSHL : + case Bytecodes.LSHL: shiftLeftLong(frame); break; - case Bytecodes.ISHR : + case Bytecodes.ISHR: shiftRightSignedInt(frame); break; - case Bytecodes.LSHR : + case Bytecodes.LSHR: shiftRightSignedLong(frame); break; - case Bytecodes.IUSHR : + case Bytecodes.IUSHR: shiftRightUnsignedInt(frame); break; - case Bytecodes.LUSHR : + case Bytecodes.LUSHR: shiftRightUnsignedLong(frame); break; - case Bytecodes.IAND : + case Bytecodes.IAND: frame.pushInt(frame.popInt() & frame.popInt()); break; - case Bytecodes.LAND : + case Bytecodes.LAND: frame.pushLong(frame.popLong() & frame.popLong()); break; - case Bytecodes.IOR : + case Bytecodes.IOR: frame.pushInt(frame.popInt() | frame.popInt()); break; - case Bytecodes.LOR : + case Bytecodes.LOR: frame.pushLong(frame.popLong() | frame.popLong()); break; - case Bytecodes.IXOR : + case Bytecodes.IXOR: frame.pushInt(frame.popInt() ^ frame.popInt()); break; - case Bytecodes.LXOR : + case Bytecodes.LXOR: frame.pushLong(frame.popLong() ^ frame.popLong()); break; - case Bytecodes.IINC : + case Bytecodes.IINC: iinc(frame, bs); break; - case Bytecodes.I2L : + case Bytecodes.I2L: frame.pushLong(frame.popInt()); break; - case Bytecodes.I2F : + case Bytecodes.I2F: frame.pushFloat(frame.popInt()); break; - case Bytecodes.I2D : + case Bytecodes.I2D: frame.pushDouble(frame.popInt()); break; - case Bytecodes.L2I : + case Bytecodes.L2I: frame.pushInt((int) frame.popLong()); break; - case Bytecodes.L2F : + case Bytecodes.L2F: frame.pushFloat(frame.popLong()); break; - case Bytecodes.L2D : + case Bytecodes.L2D: frame.pushDouble(frame.popLong()); break; - case Bytecodes.F2I : + case Bytecodes.F2I: frame.pushInt((int) frame.popFloat()); break; - case Bytecodes.F2L : + case Bytecodes.F2L: frame.pushLong((long) frame.popFloat()); break; - case Bytecodes.F2D : + case Bytecodes.F2D: frame.pushDouble(frame.popFloat()); break; - case Bytecodes.D2I : + case Bytecodes.D2I: frame.pushInt((int) frame.popDouble()); break; - case Bytecodes.D2L : + case Bytecodes.D2L: frame.pushLong((long) frame.popDouble()); break; - case Bytecodes.D2F : + case Bytecodes.D2F: frame.pushFloat((float) frame.popDouble()); break; - case Bytecodes.I2B : + case Bytecodes.I2B: frame.pushInt((byte) frame.popInt()); break; - case Bytecodes.I2C : + case Bytecodes.I2C: frame.pushInt((char) frame.popInt()); break; - case Bytecodes.I2S : + case Bytecodes.I2S: frame.pushInt((short) frame.popInt()); break; - case Bytecodes.LCMP : + case Bytecodes.LCMP: compareLong(frame); break; - case Bytecodes.FCMPL : + case Bytecodes.FCMPL: compareFloatLess(frame); break; - case Bytecodes.FCMPG : + case Bytecodes.FCMPG: compareFloatGreater(frame); break; - case Bytecodes.DCMPL : + case Bytecodes.DCMPL: compareDoubleLess(frame); break; - case Bytecodes.DCMPG : + case Bytecodes.DCMPG: compareDoubleGreater(frame); break; - case Bytecodes.IFEQ : + case Bytecodes.IFEQ: if (frame.popInt() == 0) { return BRANCH; } break; - case Bytecodes.IFNE : + case Bytecodes.IFNE: if (frame.popInt() != 0) { return BRANCH; } break; - case Bytecodes.IFLT : + case Bytecodes.IFLT: if (frame.popInt() < 0) { return BRANCH; } break; - case Bytecodes.IFGE : + case Bytecodes.IFGE: if (frame.popInt() >= 0) { return BRANCH; } break; - case Bytecodes.IFGT : + case Bytecodes.IFGT: if (frame.popInt() > 0) { return BRANCH; } break; - case Bytecodes.IFLE : + case Bytecodes.IFLE: if (frame.popInt() <= 0) { return BRANCH; } break; - case Bytecodes.IF_ICMPEQ : + case Bytecodes.IF_ICMPEQ: if (frame.popInt() == frame.popInt()) { return BRANCH; } break; - case Bytecodes.IF_ICMPNE : + case Bytecodes.IF_ICMPNE: if (frame.popInt() != frame.popInt()) { return BRANCH; } break; - case Bytecodes.IF_ICMPLT : + case Bytecodes.IF_ICMPLT: if (frame.popInt() > frame.popInt()) { return BRANCH; } break; - case Bytecodes.IF_ICMPGE : + case Bytecodes.IF_ICMPGE: if (frame.popInt() <= frame.popInt()) { return BRANCH; } break; - case Bytecodes.IF_ICMPGT : + case Bytecodes.IF_ICMPGT: if (frame.popInt() < frame.popInt()) { return BRANCH; } break; - case Bytecodes.IF_ICMPLE : + case Bytecodes.IF_ICMPLE: if (frame.popInt() >= frame.popInt()) { return BRANCH; } break; - case Bytecodes.IF_ACMPEQ : + case Bytecodes.IF_ACMPEQ: if (frame.popObject() == frame.popObject()) { return BRANCH; } break; - case Bytecodes.IF_ACMPNE : + case Bytecodes.IF_ACMPNE: if (frame.popObject() != frame.popObject()) { return BRANCH; } @@ -797,58 +794,58 @@ case Bytecodes.GOTO: case Bytecodes.GOTO_W: return BRANCH; - case Bytecodes.JSR : - case Bytecodes.JSR_W : + case Bytecodes.JSR: + case Bytecodes.JSR_W: frame.pushInt(bs.currentBCI()); return BRANCH; - case Bytecodes.RET : + case Bytecodes.RET: return frame.getInt(frame.resolveLocalIndex(bs.readLocalIndex())); - case Bytecodes.TABLESWITCH : + case Bytecodes.TABLESWITCH: return tableSwitch(frame, bs); - case Bytecodes.LOOKUPSWITCH : + case Bytecodes.LOOKUPSWITCH: return lookupSwitch(frame, bs); - case Bytecodes.IRETURN : + case Bytecodes.IRETURN: frame.getParentFrame().pushInt(frame.popInt()); return RETURN; - case Bytecodes.LRETURN : + case Bytecodes.LRETURN: frame.getParentFrame().pushLong(frame.popLong()); return RETURN; - case Bytecodes.FRETURN : + case Bytecodes.FRETURN: frame.getParentFrame().pushFloat(frame.popFloat()); return RETURN; - case Bytecodes.DRETURN : + case Bytecodes.DRETURN: frame.getParentFrame().pushDouble(frame.popDouble()); return RETURN; - case Bytecodes.ARETURN : + case Bytecodes.ARETURN: frame.getParentFrame().pushObject(frame.popObject()); return RETURN; - case Bytecodes.RETURN : + case Bytecodes.RETURN: return RETURN; - case Bytecodes.GETSTATIC : + case Bytecodes.GETSTATIC: getField(frame, null, bs.currentBC(), bs.readCPI()); break; - case Bytecodes.PUTSTATIC : + case Bytecodes.PUTSTATIC: putStatic(frame, bs.readCPI()); break; case Bytecodes.GETFIELD: getField(frame, nullCheck(frame.popObject()), bs.currentBC(), bs.readCPI()); break; - case Bytecodes.PUTFIELD : + case Bytecodes.PUTFIELD: putField(frame, bs.readCPI()); break; - case Bytecodes.INVOKEVIRTUAL : + case Bytecodes.INVOKEVIRTUAL: callFrame = invokeVirtual(frame, bs.readCPI()); if (callFrame == null) { break; } return CALL; - case Bytecodes.INVOKESPECIAL : + case Bytecodes.INVOKESPECIAL: callFrame = invokeSpecial(frame, bs.readCPI()); if (callFrame == null) { break; } return CALL; - case Bytecodes.INVOKESTATIC : + case Bytecodes.INVOKESTATIC: callFrame = invokeStatic(frame, bs.readCPI()); if (callFrame == null) { break; @@ -860,53 +857,57 @@ break; } return CALL; - case Bytecodes.XXXUNUSEDXXX : + case Bytecodes.XXXUNUSEDXXX: assert false : "unused bytecode used. behaviour unspecified."; // nop break; - case Bytecodes.NEW : + case Bytecodes.NEW: frame.pushObject(allocateInstance(frame, bs.readCPI())); break; - case Bytecodes.NEWARRAY : + case Bytecodes.NEWARRAY: frame.pushObject(allocateNativeArray(frame, bs.readByte())); break; - case Bytecodes.ANEWARRAY : + case Bytecodes.ANEWARRAY: frame.pushObject(allocateArray(frame, bs.readCPI())); break; - case Bytecodes.ARRAYLENGTH : + case Bytecodes.ARRAYLENGTH: frame.pushInt(Array.getLength(nullCheck(frame.popObject()))); break; - case Bytecodes.ATHROW : - throw (Throwable) frame.popObject(); - case Bytecodes.CHECKCAST : + case Bytecodes.ATHROW: + Throwable t = (Throwable) frame.popObject(); + if ("break".equals(t.getMessage())) { + t.printStackTrace(); + } + throw t; + case Bytecodes.CHECKCAST: checkCast(frame, bs.readCPI()); break; - case Bytecodes.INSTANCEOF : + case Bytecodes.INSTANCEOF: instanceOf(frame, bs.readCPI()); break; - case Bytecodes.MONITORENTER : + case Bytecodes.MONITORENTER: runtimeInterface.monitorEnter(frame.popObject()); break; - case Bytecodes.MONITOREXIT : + case Bytecodes.MONITOREXIT: runtimeInterface.monitorExit(frame.popObject()); break; - case Bytecodes.WIDE : + case Bytecodes.WIDE: assert false; break; - case Bytecodes.MULTIANEWARRAY : + case Bytecodes.MULTIANEWARRAY: frame.pushObject(allocateMultiArray(frame, bs.readCPI(), bs.readUByte(bs.currentBCI() + 3))); break; - case Bytecodes.IFNULL : + case Bytecodes.IFNULL: if (frame.popObject() == null) { return BRANCH; } break; - case Bytecodes.IFNONNULL : + case Bytecodes.IFNONNULL: if (frame.popObject() != null) { return BRANCH; } break; - case Bytecodes.BREAKPOINT : + case Bytecodes.BREAKPOINT: assert false : "no breakpoints supported at this time."; break; // nop } @@ -945,9 +946,8 @@ } } - private void setStackTrace(InterpreterFrame frame, Throwable t, StackTraceElement[] stackTrace) { - runtimeInterface.setFieldObject(stackTrace, t, findThrowableField(frame, "stackTrace")); + runtimeInterface.setFieldObject(stackTrace, t, findThrowableField(frame, "stackTrace")); } private StackTraceElement[] getBackTrace(InterpreterFrame frame, Throwable t) { @@ -973,10 +973,9 @@ catchType = resolveType(frame, Bytecodes.INSTANCEOF, (char) handler.catchTypeCPI()); } - if (catchType == null - || catchType.toJava().isInstance(t)) { + if (catchType == null || catchType.toJava().isInstance(t)) { // the first found exception handler is our exception handler - return handler; + return handler; } } } @@ -985,8 +984,6 @@ private InterpreterFrame allocateFrame(InterpreterFrame frame, BytecodeStream bs) { try { - stackFrameDepth++; - InterpreterFrame nextFrame = this.callFrame; assert nextFrame != null; @@ -1000,7 +997,7 @@ } if (Modifier.isSynchronized(nextFrame.getMethod().accessFlags())) { if (TRACE) { - traceOp("Method monitor enter"); + traceOp(frame, "Method monitor enter"); } if (Modifier.isStatic(nextFrame.getMethod().accessFlags())) { runtimeInterface.monitorEnter(nextFrame.getMethod().holder().toJava()); @@ -1022,7 +1019,7 @@ InterpreterFrame parent = frame.getParentFrame(); if (Modifier.isSynchronized(frame.getMethod().accessFlags())) { if (TRACE) { - traceOp("Method monitor exit"); + traceOp(frame, "Method monitor exit"); } if (Modifier.isStatic(frame.getMethod().accessFlags())) { runtimeInterface.monitorExit(frame.getMethod().holder().toJava()); @@ -1036,19 +1033,17 @@ if (TRACE) { traceCall(frame, "Ret"); } - stackFrameDepth--; frame.dispose(); return parent; } - private void traceOp(String opName) { - trace(stackFrameDepth + 1, opName); + private void traceOp(InterpreterFrame frame, String opName) { + trace(frame.depth(), opName); } private void traceCall(InterpreterFrame frame, String type) { - trace(stackFrameDepth, type + " " + - frame.getMethod() + " - " + frame.getMethod().signature().asString()); + trace(frame.depth(), type + " " + frame.getMethod() + " - " + frame.getMethod().signature().asString()); } private void trace(int level, String message) { @@ -1060,7 +1055,6 @@ System.out.println(builder); } - private void divInt(InterpreterFrame frame) { int dividend = frame.popInt(); int divisor = frame.popInt(); @@ -1085,7 +1079,6 @@ frame.pushDouble(divisor / dividend); } - private void remInt(InterpreterFrame frame) { int dividend = frame.popInt(); int divisor = frame.popInt(); @@ -1147,8 +1140,7 @@ } private int lookupSwitch(InterpreterFrame frame, BytecodeStream bs) { - return lookupSearch( - new BytecodeLookupSwitch(bs, bs.currentBCI()), frame.popInt()); + return lookupSearch(new BytecodeLookupSwitch(bs, bs.currentBCI()), frame.popInt()); } /** @@ -1169,7 +1161,7 @@ return switchHelper.bci() + switchHelper.offsetAt(mid); // key found } } - return switchHelper.defaultTarget(); // key not found. + return switchHelper.defaultTarget(); // key not found. } private int tableSwitch(InterpreterFrame frame, BytecodeStream bs) { @@ -1198,7 +1190,7 @@ return constantPool.lookupType(cpi, opcode).resolve(frame.getMethod().holder()); } - private ResolvedJavaType resolveType(InterpreterFrame frame, Class<?> javaClass) { + private ResolvedJavaType resolveType(InterpreterFrame frame, Class< ? > javaClass) { return metaAccessProvider.getResolvedJavaType(javaClass).resolve(frame.getMethod().holder()); } @@ -1215,9 +1207,7 @@ } private void instanceOf(InterpreterFrame frame, char cpi) { - frame.pushInt(resolveType(frame, Bytecodes.INSTANCEOF, cpi). - toJava().isInstance(frame.popObject()) - ? 1 : 0); + frame.pushInt(resolveType(frame, Bytecodes.INSTANCEOF, cpi).toJava().isInstance(frame.popObject()) ? 1 : 0); } private void pushCPConstant(InterpreterFrame frame, char cpi) { @@ -1227,7 +1217,7 @@ if (constant instanceof Constant) { Constant c = ((Constant) constant); switch (c.kind) { - case Int : + case Int: frame.pushInt(c.asInt()); break; case Float: @@ -1236,10 +1226,10 @@ case Object: frame.pushObject(c.asObject()); break; - case Double : + case Double: frame.pushDouble(c.asDouble()); break; - case Long : + case Long: frame.pushLong(c.asLong()); break; default: @@ -1288,6 +1278,7 @@ } return value; } + private InterpreterFrame invokeStatic(InterpreterFrame frame, char cpi) throws Throwable { return invoke(frame, resolveMethod(frame, Bytecodes.INVOKESTATIC, cpi), null); } @@ -1340,7 +1331,7 @@ } private InterpreterFrame invoke(InterpreterFrame caller, ResolvedJavaMethod method, Object receiver) throws Throwable { - if (stackFrameDepth >= maxStackFrames) { + if (caller.depth() >= maxStackFrames) { throw new StackOverflowError("Maximum callstack of " + maxStackFrames + " exceeded."); } @@ -1378,7 +1369,7 @@ // current thread is low level and we also execute the target method in the low-level interpreter Object[] originalCalleeParameters = popArgumentsAsObject(caller, originalMethod, hasReceiver); - Object[] parameters = new Object[] {caller, originalMethod, originalCalleeParameters}; + Object[] parameters = new Object[]{caller, originalMethod, originalCalleeParameters}; Object returnValue = redirectionInfo.getTargetMethod().invoke(redirectionInfo.getReceiver(), parameters); pushAsObject(caller, originalMethod.signature().returnKind(), returnValue); @@ -1415,21 +1406,21 @@ private Object allocateNativeArray(InterpreterFrame frame, byte cpi) { // the constants for the cpi are loosely defined and no real cpi indices. switch (cpi) { - case 4 : + case 4: return new byte[frame.popInt()]; - case 8 : + case 8: return new byte[frame.popInt()]; - case 5 : + case 5: return new char[frame.popInt()]; - case 7 : + case 7: return new double[frame.popInt()]; - case 6 : + case 6: return new float[frame.popInt()]; - case 10 : + case 10: return new int[frame.popInt()]; - case 11 : + case 11: return new long[frame.popInt()]; - case 9 : + case 9: return new short[frame.popInt()]; default: assert false : "unexpected case"; @@ -1456,52 +1447,52 @@ private void putFieldStatic(InterpreterFrame frame, ResolvedJavaField field) { switch (field.kind()) { - case Boolean : - case Byte : - case Char : - case Short : - case Int : + case Boolean: + case Byte: + case Char: + case Short: + case Int: runtimeInterface.setFieldInt(frame.popInt(), null, field); break; - case Double : + case Double: runtimeInterface.setFieldDouble(frame.popDouble(), null, field); break; - case Float : + case Float: runtimeInterface.setFieldFloat(frame.popFloat(), null, field); break; - case Long : + case Long: runtimeInterface.setFieldLong(frame.popLong(), null, field); break; - case Object : + case Object: runtimeInterface.setFieldObject(frame.popObject(), null, field); break; - default : + default: assert false : "unexpected case"; } } private void putFieldVirtual(InterpreterFrame frame, ResolvedJavaField field) { switch (field.kind()) { - case Boolean : - case Byte : - case Char : - case Short : - case Int : + case Boolean: + case Byte: + case Char: + case Short: + case Int: runtimeInterface.setFieldInt(frame.popInt(), nullCheck(frame.popObject()), field); break; - case Double : + case Double: runtimeInterface.setFieldDouble(frame.popDouble(), nullCheck(frame.popObject()), field); break; - case Float : + case Float: runtimeInterface.setFieldFloat(frame.popFloat(), nullCheck(frame.popObject()), field); break; - case Long : + case Long: runtimeInterface.setFieldLong(frame.popLong(), nullCheck(frame.popObject()), field); break; - case Object : + case Object: runtimeInterface.setFieldObject(frame.popObject(), nullCheck(frame.popObject()), field); break; - default : + default: assert false : "unexpected case"; } } @@ -1509,71 +1500,70 @@ private void getField(InterpreterFrame frame, Object base, int opcode, char cpi) { ResolvedJavaField field = resolveField(frame, opcode, cpi); switch (field.kind()) { - case Boolean : + case Boolean: frame.pushInt(runtimeInterface.getFieldBoolean(base, field) ? 1 : 0); break; - case Byte : + case Byte: frame.pushInt(runtimeInterface.getFieldByte(base, field)); break; - case Char : + case Char: frame.pushInt(runtimeInterface.getFieldChar(base, field)); break; - case Short : + case Short: frame.pushInt(runtimeInterface.getFieldShort(base, field)); break; - case Int : + case Int: frame.pushInt(runtimeInterface.getFieldInt(base, field)); break; - case Double : + case Double: frame.pushDouble(runtimeInterface.getFieldDouble(base, field)); break; - case Float : + case Float: frame.pushFloat(runtimeInterface.getFieldFloat(base, field)); break; - case Long : + case Long: frame.pushLong(runtimeInterface.getFieldLong(base, field)); break; - case Object : + case Object: frame.pushObject(runtimeInterface.getFieldObject(base, field)); break; - default : + default: assert false : "unexpected case"; } } - private int pushAsObject(InterpreterFrame frame, Kind typeKind, Object value) { - switch(typeKind) { - case Int : + switch (typeKind) { + case Int: frame.pushInt((int) value); break; - case Long : + case Long: frame.pushLong((long) value); return 2; - case Boolean : + case Boolean: frame.pushInt(((boolean) value) ? 1 : 0); break; - case Byte : + case Byte: frame.pushInt((byte) value); break; - case Char : + case Char: frame.pushInt((char) value); break; - case Double : + case Double: frame.pushDouble((double) value); return 2; - case Float : + case Float: frame.pushFloat((float) value); break; - case Short : + case Short: frame.pushInt((short) value); break; - case Object : + case Object: frame.pushObject(value); break; - case Void : + case Void: return 0; - default : + default: assert false : "case not specified"; } return 1; @@ -1581,27 +1571,27 @@ private Object popAsObject(InterpreterFrame frame, Kind typeKind) { switch (typeKind) { - case Boolean : + case Boolean: return frame.popInt() == 1 ? true : false; - case Byte : + case Byte: return (byte) frame.popInt(); - case Char : + case Char: return (char) frame.popInt(); - case Double : + case Double: return frame.popDouble(); - case Int : + case Int: return frame.popInt(); - case Float : + case Float: return frame.popFloat(); - case Long : + case Long: return frame.popLong(); - case Short : + case Short: return (short) frame.popInt(); - case Object : + case Object: return frame.popObject(); - case Void : + case Void: return null; - default : + default: assert false : "unexpected case"; } return null; @@ -1615,7 +1605,7 @@ } } - private static Method findMethod(Class<?> clazz, String name, Class<?> ... parameters) { + private static Method findMethod(Class< ? > clazz, String name, Class< ? >... parameters) { try { return clazz.getDeclaredMethod(name, parameters); } catch (Exception e) { @@ -1654,6 +1644,7 @@ } private class MethodRedirectionInfo { + private InterpreterCallable receiver; private Method method;
--- a/graal/com.oracle.graal.interpreter/src/com/oracle/graal/interpreter/InterpreterFrame.java Mon Jul 09 14:15:55 2012 +0200 +++ b/graal/com.oracle.graal.interpreter/src/com/oracle/graal/interpreter/InterpreterFrame.java Mon Jul 09 14:22:22 2012 +0200 @@ -37,21 +37,23 @@ private static final int SINGLE = 1; /** Pointer to the top-most stack frame element. */ + private int depth; private int tos; public InterpreterFrame(ResolvedJavaMethod method, int additionalStackSpace) { - this(method, null, additionalStackSpace); + this(method, null, additionalStackSpace, 0); } - private InterpreterFrame(ResolvedJavaMethod method, InterpreterFrame parent, int additionalStackSpace) { + private InterpreterFrame(ResolvedJavaMethod method, InterpreterFrame parent, int additionalStackSpace, int depth) { super(method.maxLocals() + method.maxStackSize() + BASE_LENGTH + additionalStackSpace, parent); setMethod(method); setBCI(0); + this.depth = depth; this.tos = BASE_LENGTH; } public InterpreterFrame create(ResolvedJavaMethod method, boolean hasReceiver) { - InterpreterFrame frame = new InterpreterFrame(method, this, 0); + InterpreterFrame frame = new InterpreterFrame(method, this, 0, this.depth + 1); int length = method.signature().argumentSlots(hasReceiver); frame.pushVoid(method.maxLocals()); @@ -67,6 +69,10 @@ return BASE_LENGTH + index; } + public int depth() { + return depth; + } + private int stackTos() { return BASE_LENGTH + getMethod().maxLocals(); }
--- a/graal/com.oracle.graal.java/src/com/oracle/graal/java/BciBlockMapping.java Mon Jul 09 14:15:55 2012 +0200 +++ b/graal/com.oracle.graal.java/src/com/oracle/graal/java/BciBlockMapping.java Mon Jul 09 14:22:22 2012 +0200 @@ -527,7 +527,7 @@ // There is a path from a loop end to the method entry that does not pass the loop header. // Therefore, the loop is non reducible (has more than one entry). // We don't want to compile such methods because the IR only supports structured loops. - throw new BailoutException("Non-reducible loop"); + throw new BailoutException("Non-reducible loop: %016x", loop); } } while (loopChanges); } @@ -629,7 +629,7 @@ } assert block.loops == 0; - block.loops = (long) 1 << (long) nextLoop; + block.loops = 1L << nextLoop; Debug.log("makeLoopHeader(%s) -> %x", block, block.loops); loopHeaders[nextLoop] = block; block.loopId = nextLoop; @@ -660,7 +660,7 @@ block.visited = true; block.active = true; - int loops = 0; + long loops = 0; for (Block successor : block.successors) { // Recursively process successors. loops |= computeBlockOrder(successor);
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.java/src/com/oracle/graal/java/BytecodeDisassembler.java Mon Jul 09 14:22:22 2012 +0200 @@ -0,0 +1,231 @@ +/* + * Copyright (c) 2012, 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. + */ +package com.oracle.graal.java; + +import static com.oracle.graal.bytecode.Bytecodes.*; + +import com.oracle.graal.api.meta.*; +import com.oracle.graal.bytecode.*; + +/** + * Utility for producing a {@code javap}-like disassembly of bytecode. + */ +public class BytecodeDisassembler { + + /** + * Specifies if the disassembly for a single instruction can span multiple lines. + */ + private final boolean multiline; + + public BytecodeDisassembler(boolean multiline) { + this.multiline = multiline; + } + + public BytecodeDisassembler() { + this(true); + } + + /** + * Disassembles the bytecode of a given method in a {@code javap}-like format. + * + * @return {@code null} if {@code method} has no bytecode (e.g., it is native or abstract) + */ + public String disassemble(ResolvedJavaMethod method) { + if (method.code() == null) { + return null; + } + ConstantPool cp = method.getConstantPool(); + BytecodeStream stream = new BytecodeStream(method.code()); + StringBuilder buf = new StringBuilder(); + int opcode = stream.currentBC(); + while (opcode != Bytecodes.END) { + int bci = stream.currentBCI(); + String mnemonic = Bytecodes.nameOf(opcode); + buf.append(String.format("%4d: %-14s", bci, mnemonic)); + if (stream.nextBCI() > bci + 1) { + switch (opcode) { + case BIPUSH : buf.append(stream.readByte()); break; + case SIPUSH : buf.append(stream.readShort()); break; + case NEW : + case CHECKCAST : + case INSTANCEOF : + case ANEWARRAY : { + int cpi = stream.readCPI(); + JavaType type = cp.lookupType(cpi, opcode); + buf.append(String.format("#%-10d // %s", cpi, MetaUtil.toJavaName(type))); + break; + } + case GETSTATIC : + case PUTSTATIC : + case GETFIELD : + case PUTFIELD : { + int cpi = stream.readCPI(); + JavaField field = cp.lookupField(cpi, opcode); + String fieldDesc = field.holder().name().equals(method.holder().name()) ? MetaUtil.format("%n:%T", field) : MetaUtil.format("%H.%n:%T", field); + buf.append(String.format("#%-10d // %s", cpi, fieldDesc)); + break; + } + case INVOKEVIRTUAL : + case INVOKESPECIAL : + case INVOKESTATIC : { + int cpi = stream.readCPI(); + JavaMethod callee = cp.lookupMethod(cpi, opcode); + String calleeDesc = callee.holder().name().equals(method.holder().name()) ? MetaUtil.format("%n:(%P)%R", callee) : MetaUtil.format("%H.%n:(%P)%R", callee); + buf.append(String.format("#%-10d // %s", cpi, calleeDesc)); + break; + } + case INVOKEINTERFACE: { + int cpi = stream.readCPI(); + JavaMethod callee = cp.lookupMethod(cpi, opcode); + String calleeDesc = callee.holder().name().equals(method.holder().name()) ? MetaUtil.format("%n:(%P)%R", callee) : MetaUtil.format("%H.%n:(%P)%R", callee); + buf.append(String.format("#%-10s // %s", cpi + ", " + stream.readUByte(bci + 3), calleeDesc)); + break; + } + case LDC : + case LDC_W : + case LDC2_W : { + int cpi = stream.readCPI(); + Object constant = cp.lookupConstant(cpi); + String desc = null; + if (constant instanceof Constant) { + Constant c = ((Constant) constant); + switch (c.kind) { + case Int : + desc = String.valueOf(c.asInt()); + break; + case Float: + desc = String.valueOf(c.asFloat()); + break; + case Object: + desc = Kind.Object.format(c.asObject()); + break; + case Double : + desc = String.valueOf(c.asDouble()); + break; + case Long : + desc = String.valueOf(c.asLong()); + break; + default: + desc = c.toString(); + break; + } + } else { + desc = constant.toString(); + } + if (!multiline) { + desc.replaceAll("\\n", ""); + } + buf.append(String.format("#%-10d // %s", cpi, desc)); + break; + } + case RET : + case ILOAD : + case LLOAD : + case FLOAD : + case DLOAD : + case ALOAD : + case ISTORE : + case LSTORE : + case FSTORE : + case DSTORE : + case ASTORE : { + buf.append(String.format("%d", stream.readLocalIndex())); + break; + } + case IFEQ : + case IFNE : + case IFLT : + case IFGE : + case IFGT : + case IFLE : + case IF_ICMPEQ : + case IF_ICMPNE : + case IF_ICMPLT : + case IF_ICMPGE : + case IF_ICMPGT : + case IF_ICMPLE : + case IF_ACMPEQ : + case IF_ACMPNE : + case GOTO : + case JSR : + case IFNULL : + case IFNONNULL : + case GOTO_W : + case JSR_W : { + buf.append(String.format("%d", stream.readBranchDest())); + break; + } + case LOOKUPSWITCH : + case TABLESWITCH : { + BytecodeSwitch bswitch = opcode == LOOKUPSWITCH ? new BytecodeLookupSwitch(stream, bci) : new BytecodeTableSwitch(stream, bci); + if (multiline) { + buf.append("{ // " + bswitch.numberOfCases()); + for (int i = 0; i < bswitch.numberOfCases(); i++) { + buf.append(String.format("%n %7d: %d", bswitch.keyAt(i), bswitch.targetAt(i))); + } + buf.append(String.format("%n default: %d", bswitch.defaultTarget())); + buf.append(String.format("%n }")); + } else { + buf.append("[" + bswitch.numberOfCases()).append("] {"); + for (int i = 0; i < bswitch.numberOfCases(); i++) { + buf.append(String.format("%d: %d", bswitch.keyAt(i), bswitch.targetAt(i))); + if (i != bswitch.numberOfCases() - 1) { + buf.append(", "); + } + } + buf.append(String.format("} default: %d", bswitch.defaultTarget())); + } + break; + } + case NEWARRAY : { + int code = stream.readLocalIndex(); + // Checkstyle: stop + switch (code) { + case 4: buf.append("boolean"); break; + case 5: buf.append("char"); break; + case 6: buf.append("float"); break; + case 7: buf.append("double"); break; + case 8: buf.append("byte"); break; + case 9: buf.append("short"); break; + case 10: buf.append("int"); break; + case 11: buf.append("long"); break; + } + // Checkstyle: resume + + break; + } + case MULTIANEWARRAY : { + int cpi = stream.readCPI(); + JavaType type = cp.lookupType(cpi, opcode); + buf.append(String.format("#%-10s // %s", cpi + ", " + stream.readUByte(bci + 3), MetaUtil.toJavaName(type))); + break; + } + } + } + buf.append(String.format("%n")); + stream.next(); + opcode = stream.currentBC(); + } + return buf.toString(); + } +}
--- a/graal/com.oracle.graal.java/src/com/oracle/graal/java/GraphBuilderPhase.java Mon Jul 09 14:15:55 2012 +0200 +++ b/graal/com.oracle.graal.java/src/com/oracle/graal/java/GraphBuilderPhase.java Mon Jul 09 14:22:22 2012 +0200 @@ -30,8 +30,8 @@ import com.oracle.graal.api.code.*; import com.oracle.graal.api.meta.*; -import com.oracle.graal.api.meta.JavaType.*; -import com.oracle.graal.api.meta.JavaTypeProfile.*; +import com.oracle.graal.api.meta.JavaType.Representation; +import com.oracle.graal.api.meta.JavaTypeProfile.ProfiledType; import com.oracle.graal.bytecode.*; import com.oracle.graal.compiler.*; import com.oracle.graal.compiler.phases.*; @@ -649,7 +649,7 @@ ResolvedJavaType resolvedType = (ResolvedJavaType) type; ConstantNode hub = appendConstant(resolvedType.getEncoding(JavaType.Representation.ObjectHub)); InstanceOfNode instanceOfNode = new InstanceOfNode(hub, (ResolvedJavaType) type, object, getProfileForTypeCheck(resolvedType)); - frameState.ipush(append(MaterializeNode.create(currentGraph.unique(instanceOfNode), currentGraph))); + frameState.ipush(append(MaterializeNode.create(currentGraph.unique(instanceOfNode)))); } else { BlockPlaceholderNode successor = currentGraph.add(new BlockPlaceholderNode()); DeoptimizeNode deopt = currentGraph.add(new DeoptimizeNode(DeoptimizationAction.InvalidateRecompile, DeoptimizationReason.Unresolved, graphId)); @@ -693,10 +693,10 @@ // Checkstyle: resume } - private void genNewTypeArray(int typeCode) { + private void genNewPrimitiveArray(int typeCode) { Kind kind = arrayTypeCodeToKind(typeCode); ResolvedJavaType elementType = runtime.getResolvedJavaType(kind); - NewTypeArrayNode nta = currentGraph.add(new NewTypeArrayNode(frameState.ipop(), elementType)); + NewPrimitiveArrayNode nta = currentGraph.add(new NewPrimitiveArrayNode(frameState.ipop(), elementType)); frameState.apush(append(nta)); } @@ -1144,7 +1144,7 @@ int pos = 0; ArrayList<Block> exitLoops = new ArrayList<>(Long.bitCount(exits)); do { - int lMask = 1 << pos; + long lMask = 1L << pos; if ((exits & lMask) != 0) { exitLoops.add(loopHeaders[pos]); exits &= ~lMask; @@ -1187,7 +1187,7 @@ } private FixedNode createTarget(double probability, Block block, FrameStateBuilder stateAfter) { - assert probability >= 0 && probability <= 1; + assert probability >= 0 && probability <= 1.01 : probability; if (probability == 0 && optimisticOpts.removeNeverExecutedCode()) { return currentGraph.add(new DeoptimizeNode(DeoptimizationAction.InvalidateReprofile, DeoptimizationReason.UnreachedCode, graphId)); } else { @@ -1709,7 +1709,7 @@ case INVOKESTATIC : cpi = stream.readCPI(); genInvokeStatic(lookupMethod(cpi, opcode)); break; case INVOKEINTERFACE: cpi = stream.readCPI(); genInvokeInterface(lookupMethod(cpi, opcode)); break; case NEW : genNewInstance(stream.readCPI()); break; - case NEWARRAY : genNewTypeArray(stream.readLocalIndex()); break; + case NEWARRAY : genNewPrimitiveArray(stream.readLocalIndex()); break; case ANEWARRAY : genNewObjectArray(stream.readCPI()); break; case ARRAYLENGTH : genArrayLength(); break; case ATHROW : genThrow(); break;
--- a/graal/com.oracle.graal.lir.amd64/src/com/oracle/graal/lir/amd64/AMD64Call.java Mon Jul 09 14:15:55 2012 +0200 +++ b/graal/com.oracle.graal.lir.amd64/src/com/oracle/graal/lir/amd64/AMD64Call.java Mon Jul 09 14:22:22 2012 +0200 @@ -34,7 +34,7 @@ import com.oracle.graal.lir.LIRInstruction.Opcode; import com.oracle.graal.lir.asm.*; import com.oracle.max.asm.target.amd64.*; -import com.oracle.max.cri.xir.CiXirAssembler.XirMark; +import com.oracle.max.cri.xir.XirAssembler.XirMark; public class AMD64Call {
--- a/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/asm/TargetMethodAssembler.java Mon Jul 09 14:15:55 2012 +0200 +++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/asm/TargetMethodAssembler.java Mon Jul 09 14:22:22 2012 +0200 @@ -111,51 +111,7 @@ Debug.metric("SafepointsEmitted").add(targetMethod.getSafepoints().size()); Debug.metric("DataPatches").add(targetMethod.getDataReferences().size()); Debug.metric("ExceptionHandlersEmitted").add(targetMethod.getExceptionHandlers().size()); - Debug.log("Finished target method %s, isStub %b", name, isStub); -/* - if (GraalOptions.PrintAssembly && !TTY.isSuppressed() && !isStub) { - Util.printSection("Target Method", Util.SECTION_CHARACTER); - TTY.println("Name: " + name); - TTY.println("Frame size: " + targetMethod.frameSize()); - TTY.println("Register size: " + asm.target.arch.registerReferenceMapBitCount); - - if (GraalOptions.PrintCodeBytes) { - Util.printSection("Code", Util.SUB_SECTION_CHARACTER); - TTY.println("Code: %d bytes", targetMethod.targetCodeSize()); - Util.printBytes(0L, targetMethod.targetCode(), 0, targetMethod.targetCodeSize(), GraalOptions.PrintAssemblyBytesPerLine); - } - - Util.printSection("Disassembly", Util.SUB_SECTION_CHARACTER); - String disassembly = runtime.disassemble(targetMethod); - TTY.println(disassembly); - boolean noDis = disassembly == null || disassembly.length() == 0; - - Util.printSection("Safepoints", Util.SUB_SECTION_CHARACTER); - for (CiTargetMethod.Safepoint x : targetMethod.safepoints) { - TTY.println(x.toString()); - if (noDis && x.debugInfo != null) { - TTY.println(CiUtil.indent(x.debugInfo.toString(), " ")); - } - } - - Util.printSection("Data Patches", Util.SUB_SECTION_CHARACTER); - for (CiTargetMethod.DataPatch x : targetMethod.dataReferences) { - TTY.println(x.toString()); - } - - Util.printSection("Marks", Util.SUB_SECTION_CHARACTER); - for (CiTargetMethod.Mark x : targetMethod.marks) { - TTY.println(x.toString()); - } - - Util.printSection("Exception Handlers", Util.SUB_SECTION_CHARACTER); - for (CiTargetMethod.ExceptionHandler x : targetMethod.exceptionHandlers) { - TTY.println(x.toString()); - } - } -*/ - return targetMethod; }
--- a/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/cfg/Block.java Mon Jul 09 14:15:55 2012 +0200 +++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/cfg/Block.java Mon Jul 09 14:22:22 2012 +0200 @@ -156,6 +156,18 @@ public Iterator<FixedNode> iterator() { return new NodeIterator(); } + + @Override + public String toString() { + StringBuilder str = new StringBuilder().append('['); + for (FixedNode node : this) { + str.append(node).append(", "); + } + if (str.length() > 1) { + str.setLength(str.length() - 2); + } + return str.append(']').toString(); + } }; }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/IfNode.java Mon Jul 09 14:15:55 2012 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/IfNode.java Mon Jul 09 14:22:22 2012 +0200 @@ -146,7 +146,7 @@ return; } if (trueValue.isConstant() && falseValue.isConstant()) { - MaterializeNode materialize = MaterializeNode.create(compare(), graph(), trueValue, falseValue); + MaterializeNode materialize = MaterializeNode.create(compare(), trueValue, falseValue); ((StructuredGraph) graph()).replaceFloating(singlePhi, materialize); removeEmptyIf(tool); return;
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/MaterializeNode.java Mon Jul 09 14:15:55 2012 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/MaterializeNode.java Mon Jul 09 14:22:22 2012 +0200 @@ -27,18 +27,59 @@ public final class MaterializeNode extends ConditionalNode { + private static CompareNode createCompareNode(Condition condition, ValueNode x, ValueNode y) { + assert x.kind() == y.kind(); + assert condition.isCanonical() : "condition is not canonical: " + condition; + + assert !x.kind().isFloatOrDouble(); + CompareNode comparison; + if (condition == Condition.EQ) { + if (x.kind().isObject()) { + comparison = new ObjectEqualsNode(x, y); + } else { + assert x.kind().stackKind().isInt() || x.kind().isLong(); + comparison = new IntegerEqualsNode(x, y); + } + } else if (condition == Condition.LT) { + assert x.kind().stackKind().isInt() || x.kind().isLong(); + comparison = new IntegerLessThanNode(x, y); + } else { + assert condition == Condition.BT; + assert x.kind().stackKind().isInt() || x.kind().isLong(); + comparison = new IntegerBelowThanNode(x, y); + } + + return x.graph().unique(comparison); + } + + private MaterializeNode(Condition condition, ValueNode x, ValueNode y) { + this(createCompareNode(condition, x, y), ConstantNode.forInt(1, x.graph()), ConstantNode.forInt(0, x.graph())); + } + private MaterializeNode(BooleanNode condition, ValueNode trueValue, ValueNode falseValue) { super(condition, trueValue, falseValue); } - public static MaterializeNode create(BooleanNode condition, Graph graph, ValueNode trueValue, ValueNode falseValue) { + public static MaterializeNode create(BooleanNode condition, ValueNode trueValue, ValueNode falseValue) { + Graph graph = condition.graph(); MaterializeNode result = new MaterializeNode(condition, trueValue, falseValue); return graph.unique(result); } - public static MaterializeNode create(BooleanNode condition, Graph graph) { - return create(condition, graph, ConstantNode.forInt(1, graph), ConstantNode.forInt(0, graph)); + public static MaterializeNode create(BooleanNode condition) { + return create(condition, ConstantNode.forInt(1, condition.graph()), ConstantNode.forInt(0, condition.graph())); } + @NodeIntrinsic + @SuppressWarnings("unused") + public static boolean materialize(@ConstantNodeParameter Condition condition, int x, int y) { + throw new UnsupportedOperationException("This method may only be compiled with the Graal compiler"); + } + + @NodeIntrinsic + @SuppressWarnings("unused") + public static boolean materialize(@ConstantNodeParameter Condition condition, long x, long y) { + throw new UnsupportedOperationException("This method may only be compiled with the Graal compiler"); + } }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/PhiNode.java Mon Jul 09 14:15:55 2012 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/PhiNode.java Mon Jul 09 14:22:22 2012 +0200 @@ -80,6 +80,11 @@ return merge; } + public void setMerge(MergeNode x) { + updateUsages(merge, x); + merge = x; + } + public NodeInputList<ValueNode> values() { return values; }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/Condition.java Mon Jul 09 14:15:55 2012 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/Condition.java Mon Jul 09 14:22:22 2012 +0200 @@ -240,9 +240,10 @@ /** * Attempts to fold a comparison between two constants and return the result. + * * @param lt the constant on the left side of the comparison * @param rt the constant on the right side of the comparison - * @param runtime the RiRuntime (might be needed to compare runtime-specific types) + * @param runtime needed to compare runtime-specific types * @return {@link Boolean#TRUE} if the comparison is known to be true, * {@link Boolean#FALSE} if the comparison is known to be false */ @@ -253,9 +254,10 @@ /** * Attempts to fold a comparison between two constants and return the result. + * * @param lt the constant on the left side of the comparison * @param rt the constant on the right side of the comparison - * @param runtime the RiRuntime (might be needed to compare runtime-specific types) + * @param runtime needed to compare runtime-specific types * @param unorderedIsTrue true if an undecided float comparison should result in "true" * @return true if the comparison is known to be true, false if the comparison is known to be false */
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/NormalizeCompareNode.java Mon Jul 09 14:15:55 2012 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/NormalizeCompareNode.java Mon Jul 09 14:22:22 2012 +0200 @@ -58,8 +58,8 @@ lessComp = graph.unique(new IntegerLessThanNode(x(), y())); } - MaterializeNode equalValue = MaterializeNode.create(equalComp, graph, ConstantNode.forInt(0, graph), ConstantNode.forInt(1, graph)); - MaterializeNode value = MaterializeNode.create(lessComp, graph, ConstantNode.forInt(-1, graph), equalValue); + MaterializeNode equalValue = MaterializeNode.create(equalComp, ConstantNode.forInt(0, graph), ConstantNode.forInt(1, graph)); + MaterializeNode value = MaterializeNode.create(lessComp, ConstantNode.forInt(-1, graph), equalValue); graph.replaceFloating(this, value); }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/ValueAnchorNode.java Mon Jul 09 14:15:55 2012 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/ValueAnchorNode.java Mon Jul 09 14:22:22 2012 +0200 @@ -37,7 +37,7 @@ public final class ValueAnchorNode extends FixedWithNextNode implements Canonicalizable, LIRLowerable, Node.IterableNodeType { public ValueAnchorNode(ValueNode... values) { - super(StampFactory.forVoid(), values); + super(StampFactory.dependency(), values); } @Override
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/NewArrayNode.java Mon Jul 09 14:15:55 2012 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/NewArrayNode.java Mon Jul 09 14:22:22 2012 +0200 @@ -36,7 +36,7 @@ /** * The {@code NewArrayNode} class is the base of all instructions that allocate arrays. */ -public abstract class NewArrayNode extends FixedWithNextNode implements EscapeAnalyzable, TypeFeedbackProvider { +public abstract class NewArrayNode extends FixedWithNextNode implements Lowerable, EscapeAnalyzable, TypeFeedbackProvider { @Input private ValueNode length; @@ -86,6 +86,11 @@ return ESCAPE; } + @Override + public void lower(LoweringTool tool) { + tool.getRuntime().lower(this, tool); + } + private static final EscapeOp ESCAPE = new EscapeOp() { @Override
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/NewPrimitiveArrayNode.java Mon Jul 09 14:22:22 2012 +0200 @@ -0,0 +1,51 @@ +/* + * Copyright (c) 2009, 2011, 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. + */ +package com.oracle.graal.nodes.java; + +import com.oracle.graal.api.meta.*; +import com.oracle.graal.nodes.*; +import com.oracle.graal.nodes.spi.*; +import com.oracle.graal.nodes.type.*; + +/** + * The {@code NewPrimitiveArrayNode} class definition. + */ +public final class NewPrimitiveArrayNode extends NewArrayNode implements LIRLowerable { + + private final ResolvedJavaType elementType; + + public NewPrimitiveArrayNode(ValueNode length, ResolvedJavaType elementType) { + super(StampFactory.exactNonNull(elementType.arrayOf()), length); + this.elementType = elementType; + } + + @Override + public ResolvedJavaType elementType() { + return elementType; + } + + @Override + public void generate(LIRGeneratorTool gen) { + gen.visitNewPrimitiveArray(this); + } +}
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/NewTypeArrayNode.java Mon Jul 09 14:15:55 2012 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,51 +0,0 @@ -/* - * Copyright (c) 2009, 2011, 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. - */ -package com.oracle.graal.nodes.java; - -import com.oracle.graal.api.meta.*; -import com.oracle.graal.nodes.*; -import com.oracle.graal.nodes.spi.*; -import com.oracle.graal.nodes.type.*; - -/** - * The {@code NewTypeArrayNode} class definition. - */ -public final class NewTypeArrayNode extends NewArrayNode implements LIRLowerable { - - private final ResolvedJavaType elementType; - - public NewTypeArrayNode(ValueNode length, ResolvedJavaType elementType) { - super(StampFactory.exactNonNull(elementType.arrayOf()), length); - this.elementType = elementType; - } - - @Override - public ResolvedJavaType elementType() { - return elementType; - } - - @Override - public void generate(LIRGeneratorTool gen) { - gen.visitNewTypeArray(this); - } -}
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/spi/GraalCodeCacheProvider.java Mon Jul 09 14:15:55 2012 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/spi/GraalCodeCacheProvider.java Mon Jul 09 14:22:22 2012 +0200 @@ -37,7 +37,4 @@ void lower(Node n, LoweringTool tool); StructuredGraph intrinsicGraph(ResolvedJavaMethod caller, int bci, ResolvedJavaMethod method, List<? extends Node> parameters); - - CompilationResult compile(ResolvedJavaMethod method, StructuredGraph graph); - }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/spi/LIRGeneratorTool.java Mon Jul 09 14:15:55 2012 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/spi/LIRGeneratorTool.java Mon Jul 09 14:22:22 2012 +0200 @@ -112,7 +112,7 @@ public abstract void visitMonitorEnter(MonitorEnterNode i); public abstract void visitMonitorExit(MonitorExitNode i); public abstract void visitNewInstance(NewInstanceNode i); - public abstract void visitNewTypeArray(NewTypeArrayNode i); + public abstract void visitNewPrimitiveArray(NewPrimitiveArrayNode i); public abstract void visitNewObjectArray(NewObjectArrayNode i); public abstract void visitNewMultiArray(NewMultiArrayNode i); public abstract void visitExceptionObject(ExceptionObjectNode i);
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/spi/types/ObjectTypeFeedbackStore.java Mon Jul 09 14:15:55 2012 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/spi/types/ObjectTypeFeedbackStore.java Mon Jul 09 14:22:22 2012 +0200 @@ -498,15 +498,15 @@ /* // equals contains all the values that might happen to be in this variable. If it is null then there is no information about possible values. // If it is empty, then we're currently in a branch that will be removed by canonicalization later on. - private Set<CiConstant> equals; + private Set<Constant> equals; // notEquals contains all the values that cannot be in this variable. - private Set<CiConstant> notEquals; + private Set<Constant> notEquals; private HashMap<ValueNode, Condition> valueBounds; - private Set<RiResolvedType> exactTypes; + private Set<ResolvedJavaType> exactTypes; - private Set<RiResolvedType> declaredTypes; + private Set<ResolvedJavaType> declaredTypes; private final TypeFeedbackChanged changed; private Node dependency; @@ -536,7 +536,7 @@ } @Override - public void constantBound(Condition condition, CiConstant constant) { + public void constantBound(Condition condition, Constant constant) { assert condition == Condition.EQ || condition == Condition.NE; if (condition == Condition.EQ) { @@ -594,15 +594,15 @@ } @Override - public void declaredType(RiResolvedType type, boolean nonNull) { + public void declaredType(ResolvedJavaType type, boolean nonNull) { if (declaredTypes == null) { declaredTypes = new HashSet<>(); declaredTypes.add(type); updateDependency(); } else { if (type.isInterface()) { - for (Iterator<RiResolvedType> iter = declaredTypes.iterator(); iter.hasNext();) { - RiResolvedType declaredType = iter.next(); + for (Iterator<ResolvedJavaType> iter = declaredTypes.iterator(); iter.hasNext();) { + ResolvedJavaType declaredType = iter.next(); if (declaredType.isInterface()) { if (type.isSubtypeOf(declaredType)) { iter.remove(); @@ -616,8 +616,8 @@ updateDependency(); } } else { - for (Iterator<RiResolvedType> iter = declaredTypes.iterator(); iter.hasNext();) { - RiResolvedType declaredType = iter.next(); + for (Iterator<ResolvedJavaType> iter = declaredTypes.iterator(); iter.hasNext();) { + ResolvedJavaType declaredType = iter.next(); if (!declaredType.isInterface()) { if (type.isSubtypeOf(declaredType)) { iter.remove(); @@ -633,12 +633,12 @@ } } if (nonNull) { - constantBound(Condition.NE, CiConstant.NULL_OBJECT); + constantBound(Condition.NE, Constant.NULL_OBJECT); } } @Override - public void exactType(RiResolvedType type) { + public void exactType(ResolvedJavaType type) { if (exactTypes == null) { exactTypes = new HashSet<>(); exactTypes.add(type); @@ -653,15 +653,15 @@ exactTypes.clear(); } } - constantBound(Condition.NE, CiConstant.NULL_OBJECT); + constantBound(Condition.NE, Constant.NULL_OBJECT); } @Override - public void notDeclaredType(RiResolvedType type, boolean nonNull) { + public void notDeclaredType(ResolvedJavaType type, boolean nonNull) { } @Override - public void notExactType(RiResolvedType type) { + public void notExactType(ResolvedJavaType type) { } @Override @@ -673,8 +673,8 @@ equals = null; } if (notEquals != null && !notEquals.isEmpty() && other.notEquals != null && !other.notEquals.isEmpty()) { - for (Iterator<CiConstant> iter = notEquals.iterator(); iter.hasNext();) { - CiConstant constant = iter.next(); + for (Iterator<Constant> iter = notEquals.iterator(); iter.hasNext();) { + Constant constant = iter.next(); if (!other.notEquals.contains(constant)) { iter.remove(); } @@ -727,7 +727,7 @@ str.append(equals.iterator().next()); } else { str.append("("); - for (CiConstant constant : equals) { + for (Constant constant : equals) { str.append(constant).append(','); } str.setLength(str.length() - 1); @@ -741,7 +741,7 @@ str.append(notEquals.iterator().next()); } else { str.append("("); - for (CiConstant constant : notEquals) { + for (Constant constant : notEquals) { str.append(constant).append(','); } str.setLength(str.length() - 1); @@ -756,7 +756,7 @@ } if (declaredTypes != null) { str.append("declared ("); - for (RiResolvedType type: declaredTypes) { + for (ResolvedJavaType type: declaredTypes) { str.append(type).append(','); } str.setLength(str.length() - 1); @@ -764,7 +764,7 @@ } if (exactTypes != null) { str.append("exact ("); - for (RiResolvedType type: exactTypes) { + for (ResolvedJavaType type: exactTypes) { str.append(type).append(','); } str.setLength(str.length() - 1);
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/type/FloatStamp.java Mon Jul 09 14:15:55 2012 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/type/FloatStamp.java Mon Jul 09 14:22:22 2012 +0200 @@ -27,25 +27,116 @@ public class FloatStamp extends Stamp { + private final double lowerBound; + private final double upperBound; + private final boolean nonNaN; + protected FloatStamp(Kind kind) { + this(kind, Double.NEGATIVE_INFINITY, Double.POSITIVE_INFINITY, false); + assert kind == Kind.Float || kind == Kind.Double; + } + + protected FloatStamp(Kind kind, double lowerBound, double upperBound, boolean nonNaN) { super(kind); - assert kind == Kind.Float || kind == Kind.Double; + assert (!nonNaN && Double.isNaN(lowerBound) && Double.isNaN(upperBound)) || lowerBound <= upperBound; + this.lowerBound = lowerBound; + this.upperBound = upperBound; + this.nonNaN = nonNaN; + } + + /** + * The (inclusive) lower bound on the value described by this stamp. + */ + public double lowerBound() { + return lowerBound; + } + + /** + * The (inclusive) upper bound on the value described by this stamp. + */ + public double upperBound() { + return upperBound; + } + + public boolean isUnrestricted() { + return lowerBound == Double.NEGATIVE_INFINITY && upperBound == Double.POSITIVE_INFINITY && !nonNaN; + } + + public boolean contains(double value) { + if (Double.isNaN(value)) { + return !nonNaN; + } else { + return value >= lowerBound && value <= upperBound; + } } @Override public String toString() { - return "" + kind().typeChar; + StringBuilder str = new StringBuilder(); + str.append(kind().typeChar); + str.append(nonNaN ? "!" : ""); + if (lowerBound == upperBound) { + str.append(" [").append(lowerBound).append(']'); + } else if (lowerBound != Double.NEGATIVE_INFINITY || upperBound != Double.POSITIVE_INFINITY) { + str.append(" [").append(lowerBound).append(" - ").append(upperBound).append(']'); + } + return str.toString(); + } + + @Override + public boolean alwaysDistinct(Stamp otherStamp) { + FloatStamp other = (FloatStamp) otherStamp; + return (nonNaN || other.nonNaN) && (lowerBound > other.upperBound || upperBound < other.lowerBound); + } + + @Override + public Stamp meet(Stamp otherStamp) { + FloatStamp other = (FloatStamp) otherStamp; + assert kind() == other.kind(); + double meetUpperBound = Math.max(upperBound, other.upperBound); + double meetLowerBound = Math.min(lowerBound, other.lowerBound); + boolean meetNonNaN = nonNaN && other.nonNaN; + if (meetLowerBound == lowerBound && meetUpperBound == upperBound && meetNonNaN == nonNaN) { + return this; + } else if (meetLowerBound == other.lowerBound && meetUpperBound == other.upperBound && meetNonNaN == other.nonNaN) { + return other; + } else { + return new FloatStamp(kind(), meetLowerBound, meetUpperBound, meetNonNaN); + } } @Override - public boolean alwaysDistinct(Stamp other) { - return false; + public int hashCode() { + final int prime = 31; + int result = 1; + long temp; + temp = Double.doubleToLongBits(lowerBound); + result = prime * result + (int) (temp ^ (temp >>> 32)); + result = prime * result + (nonNaN ? 1231 : 1237); + temp = Double.doubleToLongBits(upperBound); + result = prime * result + (int) (temp ^ (temp >>> 32)); + return result; } @Override - public Stamp meet(Stamp other) { - assert kind() == other.kind(); - return this; + public boolean equals(Object obj) { + if (this == obj) { + return true; + } + if (obj == null || getClass() != obj.getClass()) { + return false; + } + FloatStamp other = (FloatStamp) obj; + if (Double.doubleToLongBits(lowerBound) != Double.doubleToLongBits(other.lowerBound)) { + return false; + } + if (Double.doubleToLongBits(upperBound) != Double.doubleToLongBits(other.upperBound)) { + return false; + } + if (nonNaN != other.nonNaN) { + return false; + } + return true; } }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/type/IntegerStamp.java Mon Jul 09 14:15:55 2012 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/type/IntegerStamp.java Mon Jul 09 14:22:22 2012 +0200 @@ -111,6 +111,8 @@ long meetMask = mask | other.mask; if (meetLowerBound == lowerBound && meetUpperBound == upperBound && meetMask == mask) { return this; + } else if (meetLowerBound == other.lowerBound && meetUpperBound == other.upperBound && meetMask == other.mask) { + return other; } else { return new IntegerStamp(kind(), meetLowerBound, meetUpperBound, meetMask); } @@ -122,6 +124,7 @@ int result = 1; result = prime * result + (int) (lowerBound ^ (lowerBound >>> 32)); result = prime * result + (int) (upperBound ^ (upperBound >>> 32)); + result = prime * result + (int) (mask ^ (mask >>> 32)); return result; }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/type/StampFactory.java Mon Jul 09 14:15:55 2012 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/type/StampFactory.java Mon Jul 09 14:22:22 2012 +0200 @@ -102,6 +102,10 @@ return new IntegerStamp(kind, lowerBound, upperBound, mask); } + public static Stamp forFloat(Kind kind, double lowerBound, double upperBound, boolean nonNaN) { + return new FloatStamp(kind, lowerBound, upperBound, nonNaN); + } + public static Stamp forConstant(Constant value) { assert value.kind != Kind.Object; if (value.kind == Kind.Object) { @@ -109,6 +113,8 @@ } else { if (value.kind == Kind.Int || value.kind == Kind.Long) { return forInteger(value.kind, value.asLong(), value.asLong(), value.asLong() & IntegerStamp.defaultMask(value.kind)); + } else if (value.kind == Kind.Float || value.kind == Kind.Double) { + return forFloat(value.kind, value.asDouble(), value.asDouble(), !Double.isNaN(value.asDouble())); } return forKind(value.kind.stackKind()); } @@ -120,7 +126,7 @@ ResolvedJavaType type = value.isNull() ? null : runtime.getTypeOf(value); return new ObjectStamp(type, value.isNonNull(), value.isNonNull()); } else { - throw new GraalInternalError("CiKind.Object expected, actual kind: %s", value.kind); + throw new GraalInternalError(Kind.Object + " expected, actual kind: %s", value.kind); } }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/util/GraphUtil.java Mon Jul 09 14:15:55 2012 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/util/GraphUtil.java Mon Jul 09 14:22:22 2012 +0200 @@ -222,4 +222,23 @@ } return v; } + + /** + * Returns a string representation of the given collection of objects. + * + * @param objects The {@link Iterable} that will be used to iterate over the objects. + * @return A string of the format "[a, b, ...]". + */ + public static String toString(Iterable< ? > objects) { + StringBuilder str = new StringBuilder(); + str.append("["); + for (Object o : objects) { + str.append(o).append(", "); + } + if (str.length() > 1) { + str.setLength(str.length() - 2); + } + str.append("]"); + return str.toString(); + } }
--- a/graal/com.oracle.graal.printer/src/com/oracle/graal/printer/BasicIdealGraphPrinter.java Mon Jul 09 14:15:55 2012 +0200 +++ b/graal/com.oracle.graal.printer/src/com/oracle/graal/printer/BasicIdealGraphPrinter.java Mon Jul 09 14:22:22 2012 +0200 @@ -134,6 +134,12 @@ stream.println(" ]]></bytecodes>"); } + protected void printBytecodes(String disassembly) { + beginBytecodes(); + stream.println(disassembly); + endBytecodes(); + } + protected void endMethod() { stream.println(" </method>"); }
--- a/graal/com.oracle.graal.printer/src/com/oracle/graal/printer/CFGPrinterObserver.java Mon Jul 09 14:15:55 2012 +0200 +++ b/graal/com.oracle.graal.printer/src/com/oracle/graal/printer/CFGPrinterObserver.java Mon Jul 09 14:22:22 2012 +0200 @@ -24,6 +24,7 @@ import java.io.*; import java.util.*; +import java.util.concurrent.atomic.*; import com.oracle.graal.alloc.util.*; import com.oracle.graal.api.code.*; @@ -46,6 +47,7 @@ public class CFGPrinterObserver implements DebugDumpHandler { private CFGPrinter cfgPrinter; + private File cfgFile; private ResolvedJavaMethod curMethod; private List<String> curDecorators = Collections.emptyList(); @@ -63,7 +65,7 @@ * in the current debug scope and opens a new compilation scope if this pair * does not match the current method and decorator pair. */ - private void checkMethodScope() { + private boolean checkMethodScope() { ResolvedJavaMethod method = null; ArrayList<String> decorators = new ArrayList<>(); for (Object o : Debug.context()) { @@ -83,14 +85,22 @@ } } + if (method == null) { + return false; + } + if (method != curMethod || !curDecorators.equals(decorators)) { cfgPrinter.printCompilation(method); - TTY.println("CFGPrinter: Dumping method %s", method); + TTY.println("CFGPrinter: Dumping method %s to %s", method, cfgFile); curMethod = method; curDecorators = decorators; } + return true; } + private static final long timestamp = System.currentTimeMillis(); + private static final AtomicInteger uniqueId = new AtomicInteger(); + public void dumpSandboxed(Object object, String message) { GraalCompiler compiler = Debug.contextLookup(GraalCompiler.class); if (compiler == null) { @@ -98,17 +108,19 @@ } if (cfgPrinter == null) { - File file = new File("compilations-" + System.currentTimeMillis() + ".cfg"); + cfgFile = new File("compilations-" + timestamp + "_" + uniqueId.incrementAndGet() + ".cfg"); try { - OutputStream out = new BufferedOutputStream(new FileOutputStream(file)); + OutputStream out = new BufferedOutputStream(new FileOutputStream(cfgFile)); cfgPrinter = new CFGPrinter(out); } catch (FileNotFoundException e) { - throw new GraalInternalError("Could not open " + file.getAbsolutePath()); + throw new GraalInternalError("Could not open " + cfgFile.getAbsolutePath()); } - TTY.println("CFGPrinter: Output to file %s", file); + TTY.println("CFGPrinter: Output to file %s", cfgFile); } - checkMethodScope(); + if (!checkMethodScope()) { + return; + } cfgPrinter.target = compiler.target; if (object instanceof LIR) { @@ -126,7 +138,9 @@ if (object instanceof BciBlockMapping) { BciBlockMapping blockMap = (BciBlockMapping) object; cfgPrinter.printCFG(message, blockMap); - cfgPrinter.printBytecodes(runtime.disassemble(blockMap.method)); + if (blockMap.method.code() != null) { + cfgPrinter.printBytecodes(new BytecodeDisassembler(false).disassemble(blockMap.method)); + } } else if (object instanceof LIR) { cfgPrinter.printCFG(message, cfgPrinter.lir.codeEmittingOrder());
--- a/graal/com.oracle.graal.printer/src/com/oracle/graal/printer/IdealGraphPrinter.java Mon Jul 09 14:15:55 2012 +0200 +++ b/graal/com.oracle.graal.printer/src/com/oracle/graal/printer/IdealGraphPrinter.java Mon Jul 09 14:22:22 2012 +0200 @@ -27,12 +27,12 @@ import java.util.Map.Entry; import com.oracle.graal.api.meta.*; -import com.oracle.graal.bytecode.*; import com.oracle.graal.compiler.schedule.*; import com.oracle.graal.graph.*; import com.oracle.graal.graph.Node.Verbosity; import com.oracle.graal.graph.NodeClass.NodeClassIterator; import com.oracle.graal.graph.NodeClass.Position; +import com.oracle.graal.java.*; import com.oracle.graal.lir.cfg.*; import com.oracle.graal.nodes.*; @@ -57,23 +57,8 @@ printProperty("name", name); endProperties(); beginMethod(name, shortName, bci); - if (method != null) { - beginBytecodes(); - BytecodeStream bytecodes = new BytecodeStream(method.code()); - while (bytecodes.currentBC() != Bytecodes.END) { - int startBCI = bytecodes.currentBCI(); - String mnemonic = Bytecodes.nameOf(bytecodes.currentBC()); - int[] extra = null; - if (bytecodes.nextBCI() > startBCI + 1) { - extra = new int[bytecodes.nextBCI() - (startBCI + 1)]; - for (int i = 0; i < extra.length; i++) { - extra[i] = bytecodes.readUByte(startBCI + 1 + i); - } - } - printBytecode(startBCI, mnemonic, extra); - bytecodes.next(); - } - endBytecodes(); + if (method != null && method.code() != null) { + printBytecodes(new BytecodeDisassembler(false).disassemble(method)); } endMethod(); }
--- a/graal/com.oracle.graal.printer/src/com/oracle/graal/printer/IdealGraphPrinterDumpHandler.java Mon Jul 09 14:15:55 2012 +0200 +++ b/graal/com.oracle.graal.printer/src/com/oracle/graal/printer/IdealGraphPrinterDumpHandler.java Mon Jul 09 14:22:22 2012 +0200 @@ -102,7 +102,7 @@ final Graph graph = (Graph) object; if (printer != null && printer.isValid()) { - // Get all current RiResolvedMethod instances in the context. + // Get all current ResolvedJavaMethod instances in the context. List<String> inlineContext = getInlineContext(); // Reverse list such that inner method comes after outer method.
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.snippets.test/src/com/oracle/graal/snippets/CheckCastTest.java Mon Jul 09 14:22:22 2012 +0200 @@ -0,0 +1,192 @@ +/* + * Copyright (c) 2011, 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. + */ +package com.oracle.graal.snippets; + +import org.junit.*; + +import com.oracle.graal.api.meta.*; +import com.oracle.graal.nodes.*; +import com.oracle.graal.nodes.java.*; + +/** + * Tests the implementation of checkcast, allowing profiling information to + * be manually specified. + */ +public class CheckCastTest extends TypeCheckTest { + + /** + * Enables making the target type "unknown" at compile time. + */ + boolean unknown; + + @Override + protected void replaceProfile(StructuredGraph graph, JavaTypeProfile profile) { + CheckCastNode ccn = graph.getNodes(CheckCastNode.class).first(); + if (ccn != null) { + ResolvedJavaType targetClass = unknown ? null : ccn.targetClass(); + CheckCastNode ccnNew = graph.add(new CheckCastNode(ccn.targetClassInstruction(), targetClass, ccn.object(), profile)); + graph.replaceFixedWithFixed(ccn, ccnNew); + } + unknown = false; + } + + @Override + protected void test(String name, JavaTypeProfile profile, Object... args) { + super.test(name, profile, args); + unknown = true; + super.test(name, profile, args); + } + + @Test + public void test1() { + test("asNumber", profile(), 111); + test("asNumber", profile(Integer.class), 111); + test("asNumber", profile(Long.class, Short.class), 111); + test("asNumberExt", profile(), 111); + test("asNumberExt", profile(Integer.class), 111); + test("asNumberExt", profile(Long.class, Short.class), 111); + } + + @Test + public void test2() { + test("asString", profile(), "111"); + test("asString", profile(String.class), "111"); + test("asString", profile(String.class), "111"); + + final String nullString = null; + test("asString", profile(), nullString); + test("asString", profile(String.class), nullString); + test("asString", profile(String.class), nullString); + + test("asStringExt", profile(), "111"); + test("asStringExt", profile(String.class), "111"); + test("asStringExt", profile(String.class), "111"); + } + + @Test + public void test3() { + test("asNumber", profile(), "111"); + } + + @Test + public void test4() { + test("asString", profile(String.class), 111); + } + + @Test + public void test5() { + test("asNumberExt", profile(), "111"); + } + + @Test + public void test6() { + test("asStringExt", profile(String.class), 111); + } + + @Test + public void test7() { + Throwable throwable = new Exception(); + test("asThrowable", profile(), throwable); + test("asThrowable", profile(Throwable.class), throwable); + test("asThrowable", profile(Exception.class, Error.class), throwable); + } + + @Test + public void test8() { + test("arrayFill", profile(), new Object[100], "111"); + } + + public static Number asNumber(Object o) { + return (Number) o; + } + + public static String asString(Object o) { + return (String) o; + } + + public static Throwable asThrowable(Object o) { + return (Throwable) o; + } + + public static ValueNode asValueNode(Object o) { + return (ValueNode) o; + } + + public static Number asNumberExt(Object o) { + Number n = (Number) o; + return n.intValue() + 10; + } + + public static String asStringExt(Object o) { + String s = (String) o; + return "#" + s; + } + + public static Object[] arrayFill(Object[] arr, Object value) { + for (int i = 0; i < arr.length; i++) { + arr[i] = value; + } + return arr; + } + + static class Depth1 implements Cloneable {} + static class Depth2 extends Depth1 {} + static class Depth3 extends Depth2 {} + static class Depth4 extends Depth3 {} + static class Depth5 extends Depth4 {} + static class Depth6 extends Depth5 {} + static class Depth7 extends Depth6 {} + static class Depth8 extends Depth7 {} + static class Depth9 extends Depth8 {} + static class Depth10 extends Depth9 {} + static class Depth11 extends Depth10 {} + static class Depth12 extends Depth11 {} + static class Depth13 extends Depth12 {} + static class Depth14 extends Depth12 {} + + public static Depth12 asDepth12(Object o) { + return (Depth12) o; + } + + public static Depth12[][] asDepth12Arr(Object o) { + return (Depth12[][]) o; + } + + public static Cloneable asCloneable(Object o) { + return (Cloneable) o; + } + + @Test + public void test9() { + Object o = new Depth13(); + test("asDepth12", profile(), o); + test("asDepth12", profile(Depth13.class), o); + test("asDepth12", profile(Depth13.class, Depth14.class), o); + } + + @Test + public void test10() { + Object o = new Depth13[3][]; + test("asDepth12Arr", profile(), o); + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.snippets.test/src/com/oracle/graal/snippets/InstanceOfTest.java Mon Jul 09 14:22:22 2012 +0200 @@ -0,0 +1,146 @@ +/* + * Copyright (c) 2011, 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. + */ +package com.oracle.graal.snippets; + +import java.util.*; + +import org.junit.*; + +import com.oracle.graal.api.meta.*; +import com.oracle.graal.nodes.*; +import com.oracle.graal.nodes.java.*; + +/** + * Tests the implementation of instanceof, allowing profiling information to + * be manually specified. + */ +public class InstanceOfTest extends TypeCheckTest { + + @Override + protected void replaceProfile(StructuredGraph graph, JavaTypeProfile profile) { + InstanceOfNode ion = graph.getNodes().filter(InstanceOfNode.class).first(); + if (ion != null) { + InstanceOfNode ionNew = graph.add(new InstanceOfNode(ion.targetClassInstruction(), ion.targetClass(), ion.object(), profile)); + graph.replaceFloating(ion, ionNew); + } + } + + @Test + public void test1() { + test("isString", profile(), "object"); + test("isString", profile(String.class), "object"); + + test("isString", profile(), Object.class); + test("isString", profile(String.class), Object.class); + } + + @Test + public void test2() { + test("isStringInt", profile(), "object"); + test("isStringInt", profile(String.class), "object"); + + test("isStringInt", profile(), Object.class); + test("isStringInt", profile(String.class), Object.class); + } + + @Test + public void test3() { + Throwable throwable = new Exception(); + test("isThrowable", profile(), throwable); + test("isThrowable", profile(Throwable.class), throwable); + test("isThrowable", profile(Exception.class, Error.class), throwable); + + test("isThrowable", profile(), Object.class); + test("isThrowable", profile(Throwable.class), Object.class); + test("isThrowable", profile(Exception.class, Error.class), Object.class); + } + + @Test + public void test4() { + Throwable throwable = new Exception(); + test("isThrowableInt", profile(), throwable); + test("isThrowableInt", profile(Throwable.class), throwable); + test("isThrowableInt", profile(Exception.class, Error.class), throwable); + + test("isThrowableInt", profile(), Object.class); + test("isThrowableInt", profile(Throwable.class), Object.class); + test("isThrowableInt", profile(Exception.class, Error.class), Object.class); + } + + @Test + public void test5() { + Map map = new HashMap<>(); + test("isMap", profile(), map); + test("isMap", profile(HashMap.class), map); + test("isMap", profile(TreeMap.class, HashMap.class), map); + + test("isMap", profile(), Object.class); + test("isMap", profile(HashMap.class), Object.class); + test("isMap", profile(TreeMap.class, HashMap.class), Object.class); + } + + @Test + public void test6() { + Map map = new HashMap<>(); + test("isMapInt", profile(), map); + test("isMapInt", profile(HashMap.class), map); + test("isMapInt", profile(TreeMap.class, HashMap.class), map); + + test("isMapInt", profile(), Object.class); + test("isMapInt", profile(HashMap.class), Object.class); + test("isMapInt", profile(TreeMap.class, HashMap.class), Object.class); + } + + public static boolean isString(Object o) { + return o instanceof String; + } + + public static int isStringInt(Object o) { + if (o instanceof String) { + return 1; + } + return 0; + } + + public static boolean isThrowable(Object o) { + return o instanceof Throwable; + } + + public static int isThrowableInt(Object o) { + if (o instanceof Throwable) { + return 1; + } + return 0; + } + + public static boolean isMap(Object o) { + return o instanceof Map; + } + + public static int isMapInt(Object o) { + if (o instanceof Map) { + return 1; + } + return 0; + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.snippets.test/src/com/oracle/graal/snippets/InvokeTest.java Mon Jul 09 14:22:22 2012 +0200 @@ -0,0 +1,89 @@ +/* + * Copyright (c) 2011, 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. + */ +package com.oracle.graal.snippets; + +import org.junit.*; + +import com.oracle.graal.api.meta.*; +import com.oracle.graal.compiler.phases.*; +import com.oracle.graal.compiler.tests.*; +import com.oracle.graal.nodes.*; + +/** + * Tests the implementation of the snippets for lowering the INVOKE* instructions. + */ +public class InvokeTest extends GraalCompilerTest { + + @Override + protected void editPhasePlan(ResolvedJavaMethod method, StructuredGraph graph, PhasePlan phasePlan) { + phasePlan.disablePhase(InliningPhase.class); + } + + public interface I { + String virtualMethod(String s); + } + + public static class A implements I { + public String virtualMethod(String s) { + return s; + } + } + + @SuppressWarnings("static-method") + private String privateMethod(String s) { + return s; + } + + @Test + public void test1() { + test("invokestatic", "a string"); + test("invokespecialConstructor", "a string"); + test("invokespecial", this, "a string"); + test("invokevirtual", new A(), "a string"); + test("invokeinterface", new A(), "a string"); + } + + public static String invokestatic(String s) { + return staticMethod(s); + } + + public static String staticMethod(String s) { + return s; + } + + public static String invokespecialConstructor(String s) { + return new A().virtualMethod(s); + } + + public static String invokespecial(InvokeTest a, String s) { + return a.privateMethod(s); + } + + public static String invokevirtual(A a, String s) { + return a.virtualMethod(s); + } + + public static String invokeinterface(I i, String s) { + return i.virtualMethod(s); + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.snippets.test/src/com/oracle/graal/snippets/NewArrayTest.java Mon Jul 09 14:22:22 2012 +0200 @@ -0,0 +1,167 @@ +/* + * Copyright (c) 2011, 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. + */ +package com.oracle.graal.snippets; + +import org.junit.*; + +import com.oracle.graal.compiler.tests.*; + +/** + * Tests the implementation of {@code [A]NEWARRAY}. + */ +public class NewArrayTest extends GraalCompilerTest { + + @Override + protected void assertEquals(Object expected, Object actual) { + Assert.assertTrue(expected != null); + Assert.assertTrue(actual != null); + super.assertEquals(expected.getClass(), actual.getClass()); + if (expected instanceof int[]) { + Assert.assertArrayEquals((int[]) expected, (int[]) actual); + } else if (expected instanceof byte[]) { + Assert.assertArrayEquals((byte[]) expected, (byte[]) actual); + } else if (expected instanceof char[]) { + Assert.assertArrayEquals((char[]) expected, (char[]) actual); + } else if (expected instanceof short[]) { + Assert.assertArrayEquals((short[]) expected, (short[]) actual); + } else if (expected instanceof float[]) { + Assert.assertArrayEquals((float[]) expected, (float[]) actual, 0.0f); + } else if (expected instanceof long[]) { + Assert.assertArrayEquals((long[]) expected, (long[]) actual); + } else if (expected instanceof double[]) { + Assert.assertArrayEquals((double[]) expected, (double[]) actual, 0.0d); + } else if (expected instanceof Object[]) { + Assert.assertArrayEquals((Object[]) expected, (Object[]) actual); + } else { + Assert.fail("non-array value encountered: " + expected); + } + } + + @Test + public void test1() { + for (String type : new String[] {"Byte", "Char", "Short", "Int", "Float", "Long", "Double", "String"}) { + test("new" + type + "Array7"); + test("new" + type + "ArrayMinus7"); + test("new" + type + "Array", 7); + test("new" + type + "Array", -7); + test("new" + type + "Array", Integer.MAX_VALUE); + test("new" + type + "Array", Integer.MIN_VALUE); + } + } + + public static Object newCharArray7() { + return new char[7]; + } + + public static Object newCharArrayMinus7() { + return new char[-7]; + } + + public static Object newCharArray(int length) { + return new char[length]; + } + + public static Object newShortArray7() { + return new short[7]; + } + + public static Object newShortArrayMinus7() { + return new short[-7]; + } + + public static Object newShortArray(int length) { + return new short[length]; + } + + public static Object newFloatArray7() { + return new float[7]; + } + + public static Object newFloatArrayMinus7() { + return new float[-7]; + } + + public static Object newFloatArray(int length) { + return new float[length]; + } + + public static Object newLongArray7() { + return new long[7]; + } + + public static Object newLongArrayMinus7() { + return new long[-7]; + } + + public static Object newLongArray(int length) { + return new long[length]; + } + + public static Object newDoubleArray7() { + return new double[7]; + } + + public static Object newDoubleArrayMinus7() { + return new double[-7]; + } + + public static Object newDoubleArray(int length) { + return new double[length]; + } + + public static Object newIntArray7() { + return new int[7]; + } + + public static Object newIntArrayMinus7() { + return new int[-7]; + } + + public static Object newIntArray(int length) { + return new int[length]; + } + + public static Object newByteArray7() { + return new byte[7]; + } + + public static Object newByteArrayMinus7() { + return new byte[-7]; + } + + public static Object newByteArray(int length) { + return new byte[length]; + } + + public static Object newStringArray7() { + return new String[7]; + } + + public static Object newStringArrayMinus7() { + return new String[-7]; + } + + public static Object newStringArray(int length) { + return new String[length]; + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.snippets.test/src/com/oracle/graal/snippets/NewInstanceTest.java Mon Jul 09 14:22:22 2012 +0200 @@ -0,0 +1,190 @@ +/* + * Copyright (c) 2011, 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. + */ +package com.oracle.graal.snippets; + +import java.util.*; + +import org.junit.*; + +import com.oracle.graal.compiler.tests.*; + +/** + * Tests the implementation of {@code NEW}. + */ +public class NewInstanceTest extends GraalCompilerTest { + + @Override + protected void assertEquals(Object expected, Object actual) { + Assert.assertTrue(expected != null); + Assert.assertTrue(actual != null); + super.assertEquals(expected.getClass(), actual.getClass()); + if (expected.getClass() != Object.class) { + try { + expected.getClass().getDeclaredMethod("equals", Object.class); + super.assertEquals(expected, actual); + } catch (Exception e) { + } + } + } + + @Test + public void test1() { + test("newObject"); + test("newBigObject"); + test("newSomeObject"); + test("newEmptyString"); + test("newString", "value"); + test("newHashMap", 31); + test("newRegression", true); + } + + public static Object newObject() { + return new Object(); + } + + public static BigObject newBigObject() { + return new BigObject(); + } + + public static SomeObject newSomeObject() { + return new SomeObject(); + } + + public static String newEmptyString() { + return new String(); + } + + public static String newString(String value) { + return new String(value); + } + + public static HashMap newHashMap(int initialCapacity) { + return new HashMap(initialCapacity); + } + + static class SomeObject { + String name = "o1"; + HashMap<String, Object> map = new HashMap<>(); + + + public SomeObject() { + map.put(name, this.getClass()); + } + + @Override + public boolean equals(Object obj) { + if (obj instanceof SomeObject) { + SomeObject so = (SomeObject) obj; + return so.name.equals(name) && so.map.equals(map); + } + return false; + } + + @Override + public int hashCode() { + return name.hashCode(); + } + } + + static class BigObject { + Object f01; + Object f02; + Object f03; + Object f04; + Object f05; + Object f06; + Object f07; + Object f08; + Object f09; + Object f10; + Object f12; + Object f13; + Object f14; + Object f15; + Object f16; + Object f17; + Object f18; + Object f19; + Object f20; + Object f21; + Object f22; + Object f23; + Object f24; + Object f25; + Object f26; + Object f27; + Object f28; + Object f29; + Object f30; + Object f31; + Object f32; + Object f33; + Object f34; + Object f35; + Object f36; + Object f37; + Object f38; + Object f39; + Object f40; + Object f41; + Object f42; + Object f43; + Object f44; + Object f45; + } + + /** + * Tests that an earlier bug does not occur. The issue was that the loading of the TLAB + * 'top' and 'end' values was being GVN'ed from each branch of the 'if' statement. + * This meant that the allocated B object in the true branch overwrote the allocated + * array. The cause is that RegisterNode was a floating node and the reads from it + * were UnsafeLoads which are also floating. The fix was to make RegisterNode a fixed + * node (which it should have been in the first place). + */ + public static Object newRegression(boolean condition) { + Object result; + if (condition) { + Object[] arr = {0, 1, 2, 3, 4, 5}; + result = new B(); + for (int i = 0; i < arr.length; ++i) { + // If the bug exists, the values of arr will now be deadbeef values + // and the virtual dispatch will cause a segfault. This can result in + // either a VM crash or a spurious NullPointerException. + if (arr[i].equals(Integer.valueOf(i))) { + return false; + } + } + } else { + result = new B(); + } + return result; + } + + static class B { + long f1 = 0xdeadbeefdeadbe01L; + long f2 = 0xdeadbeefdeadbe02L; + long f3 = 0xdeadbeefdeadbe03L; + long f4 = 0xdeadbeefdeadbe04L; + long f5 = 0xdeadbeefdeadbe05L; + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.snippets.test/src/com/oracle/graal/snippets/TypeCheckTest.java Mon Jul 09 14:22:22 2012 +0200 @@ -0,0 +1,69 @@ +/* + * Copyright (c) 2011, 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. + */ +package com.oracle.graal.snippets; + +import com.oracle.graal.api.meta.*; +import com.oracle.graal.api.meta.JavaTypeProfile.*; +import com.oracle.graal.compiler.tests.*; +import com.oracle.graal.nodes.*; + +/** + * Base class for checkcast and instanceof test classes. + */ +public abstract class TypeCheckTest extends GraalCompilerTest { + + protected abstract void replaceProfile(StructuredGraph graph, JavaTypeProfile profile); + + protected JavaTypeProfile currentProfile; + + @Override + protected InstalledCode getCode(final ResolvedJavaMethod method, final StructuredGraph graph) { + boolean forceCompile = false; + if (currentProfile != null) { + replaceProfile(graph, currentProfile); + forceCompile = true; + } + return super.getCode(method, graph, forceCompile); + } + + protected JavaTypeProfile profile(Class... types) { + if (types.length == 0) { + return null; + } + ProfiledType[] ptypes = new ProfiledType[types.length]; + for (int i = 0; i < types.length; i++) { + ptypes[i] = new ProfiledType(runtime.getResolvedJavaType(types[i]), 1.0D / types.length); + } + return new JavaTypeProfile(0.0D, ptypes); + } + + protected void test(String name, JavaTypeProfile profile, Object... args) { + assert currentProfile == null; + currentProfile = profile; + try { + super.test(name, args); + } finally { + currentProfile = null; + } + } +}
--- a/graal/com.oracle.graal.snippets/src/com/oracle/graal/snippets/Snippet.java Mon Jul 09 14:15:55 2012 +0200 +++ b/graal/com.oracle.graal.snippets/src/com/oracle/graal/snippets/Snippet.java Mon Jul 09 14:22:22 2012 +0200 @@ -58,11 +58,26 @@ boolean shouldInline(ResolvedJavaMethod method, ResolvedJavaMethod caller); /** - * The default inlining policy which inlines everything except for - * constructors of {@link Throwable} classes. + * The default inlining policy which inlines everything except for methods + * in any of the following categories. + * <ul> + * <li>{@linkplain Fold foldable} methods</li> + * <li>{@linkplain NodeIntrinsic node intrinsics}</li> + * <li>native methods</li> + * <li>constructors of {@link Throwable} classes</li> + * </ul> */ InliningPolicy Default = new InliningPolicy() { public boolean shouldInline(ResolvedJavaMethod method, ResolvedJavaMethod caller) { + if (Modifier.isNative(method.accessFlags())) { + return false; + } + if (method.getAnnotation(Fold.class) != null) { + return false; + } + if (method.getAnnotation(NodeIntrinsic.class) != null) { + return false; + } if (Throwable.class.isAssignableFrom(method.holder().toJava())) { if (method.name().equals("<init>")) { return false;
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.snippets/src/com/oracle/graal/snippets/SnippetCounter.java Mon Jul 09 14:22:22 2012 +0200 @@ -0,0 +1,154 @@ +/* + * Copyright (c) 2012, 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. + */ +package com.oracle.graal.snippets; + +//JaCoCo Exclude + +import java.io.*; +import java.util.*; + +import sun.misc.*; + +import com.oracle.graal.graph.*; +import com.oracle.graal.snippets.Snippet.Fold; +import com.oracle.graal.snippets.nodes.*; + +/** + * A counter that can be safely {@linkplain #inc() incremented} from within a + * snippet for gathering snippet specific metrics. + */ +public class SnippetCounter implements Comparable<SnippetCounter> { + + /** + * A group of related counters. + */ + public static class Group { + final String name; + final List<SnippetCounter> counters; + + public Group(String name) { + this.name = name; + this.counters = new ArrayList<>(); + } + + @Override + public synchronized String toString() { + Collections.sort(counters); + + long total = 0; + int maxNameLen = 0; + for (SnippetCounter c : counters) { + total += c.value; + maxNameLen = Math.max(c.name.length(), maxNameLen); + } + + StringBuilder buf = new StringBuilder(String.format("Counters: %s%n", name)); + + for (SnippetCounter c : counters) { + double percent = total == 0D ? 0D : ((double) (c.value * 100)) / total; + buf.append(String.format(" %" + maxNameLen + "s: %5.2f%%%10d // %s%n", c.name, percent, c.value, c.description)); + } + return buf.toString(); + } + } + + /** + * Sorts counters in descending order of their {@linkplain #value() values}. + */ + @Override + public int compareTo(SnippetCounter o) { + if (value > o.value) { + return -1; + } else if (o.value < value) { + return 1; + } + return 0; + } + + private static final List<Group> groups = new ArrayList<>(); + + private final Group group; + private final int index; + private final String name; + private final String description; + private long value; + + @Fold + private static int countOffset() { + try { + return (int) Unsafe.getUnsafe().objectFieldOffset(SnippetCounter.class.getDeclaredField("value")); + } catch (Exception e) { + throw new GraalInternalError(e); + } + } + + /** + * Creates a counter. + * + * @param group the group to which the counter belongs. If this is null, the newly created counter is disabled and + * {@linkplain #inc() incrementing} is a no-op. + * @param name the name of the counter + * @param description a brief comment describing the metric represented by the counter + */ + public SnippetCounter(Group group, String name, String description) { + this.group = group; + this.name = name; + this.description = description; + if (group != null) { + List<SnippetCounter> counters = group.counters; + this.index = counters.size(); + counters.add(this); + if (index == 0) { + groups.add(group); + } + } else { + this.index = -1; + } + } + + /** + * Increments the value of this counter. This method can be safely used in a snippet + * if it is invoked on a compile-time constant {@link SnippetCounter} object. + */ + public void inc() { + if (group != null) { + DirectObjectStoreNode.storeLong(this, countOffset(), 0, value + 1); + } + } + + /** + * Gets the value of this counter. + */ + public long value() { + return value; + } + + /** + * Prints all the counter groups to a given stream. + */ + public static void printGroups(PrintStream out) { + for (Group group : groups) { + out.println(group); + } + } +}
--- a/graal/com.oracle.graal.snippets/src/com/oracle/graal/snippets/SnippetInstaller.java Mon Jul 09 14:15:55 2012 +0200 +++ b/graal/com.oracle.graal.snippets/src/com/oracle/graal/snippets/SnippetInstaller.java Mon Jul 09 14:22:22 2012 +0200 @@ -136,6 +136,8 @@ public StructuredGraph makeGraph(final ResolvedJavaMethod method, final InliningPolicy policy) { StructuredGraph graph = parseGraph(method, policy); + new SnippetIntrinsificationPhase(runtime, pool, SnippetTemplate.hasConstantParameter(method)).apply(graph); + Debug.dump(graph, "%s: Final", method.name()); return graph; @@ -164,7 +166,7 @@ new SnippetVerificationPhase().apply(graph); - new SnippetIntrinsificationPhase(runtime, pool).apply(graph); + new SnippetIntrinsificationPhase(runtime, pool, true).apply(graph); for (Invoke invoke : graph.getInvokes()) { MethodCallTargetNode callTarget = invoke.callTarget(); @@ -180,7 +182,7 @@ } } - new SnippetIntrinsificationPhase(runtime, pool).apply(graph); + new SnippetIntrinsificationPhase(runtime, pool, true).apply(graph); new WordTypeRewriterPhase(target.wordKind, runtime.getResolvedJavaType(target.wordKind)).apply(graph);
--- a/graal/com.oracle.graal.snippets/src/com/oracle/graal/snippets/SnippetIntrinsificationPhase.java Mon Jul 09 14:15:55 2012 +0200 +++ b/graal/com.oracle.graal.snippets/src/com/oracle/graal/snippets/SnippetIntrinsificationPhase.java Mon Jul 09 14:22:22 2012 +0200 @@ -40,16 +40,39 @@ private final MetaAccessProvider runtime; private final BoxingMethodPool pool; + private final boolean intrinsificationOrFoldingCanBeDeferred; - public SnippetIntrinsificationPhase(MetaAccessProvider runtime, BoxingMethodPool pool) { + /** + * @param intrinsificationOrFoldingCanBeDeferred if true, then {@link NonConstantParameterError}s are not fatal + */ + public SnippetIntrinsificationPhase(MetaAccessProvider runtime, BoxingMethodPool pool, boolean intrinsificationOrFoldingCanBeDeferred) { this.runtime = runtime; this.pool = pool; + this.intrinsificationOrFoldingCanBeDeferred = intrinsificationOrFoldingCanBeDeferred; } @Override protected void run(StructuredGraph graph) { for (Invoke i : graph.getInvokes()) { - tryIntrinsify(i); + try { + tryIntrinsify(i); + } catch (NonConstantParameterError t) { + if (!intrinsificationOrFoldingCanBeDeferred) { + throw t; + } + } + } + } + + /** + * Exception raised when an argument to a {@linkplain Fold foldable} or + * {@link NodeIntrinsic} method is not a constant. + */ + @SuppressWarnings("serial") + public static class NonConstantParameterError extends Error { + + public NonConstantParameterError(String message) { + super(message); } } @@ -118,7 +141,9 @@ } ValueNode argument = tryBoxingElimination(parameterIndex, target, arguments.get(i)); if (folding || MetaUtil.getParameterAnnotation(ConstantNodeParameter.class, parameterIndex, target) != null) { - assert argument instanceof ConstantNode : "parameter " + parameterIndex + " must be a compile time constant for calling " + invoke.callTarget().targetMethod() + " at " + sourceLocation(invoke.node()) + ": " + argument; + if (!(argument instanceof ConstantNode)) { + throw new NonConstantParameterError("parameter " + parameterIndex + " must be a compile time constant for calling " + invoke.callTarget().targetMethod() + " at " + sourceLocation(invoke.node()) + ": " + argument); + } ConstantNode constantNode = (ConstantNode) argument; Constant constant = constantNode.asConstant(); Object o = constant.boxedValue();
--- a/graal/com.oracle.graal.snippets/src/com/oracle/graal/snippets/SnippetTemplate.java Mon Jul 09 14:15:55 2012 +0200 +++ b/graal/com.oracle.graal.snippets/src/com/oracle/graal/snippets/SnippetTemplate.java Mon Jul 09 14:22:22 2012 +0200 @@ -35,6 +35,7 @@ import com.oracle.graal.graph.*; import com.oracle.graal.graph.Node.Verbosity; import com.oracle.graal.nodes.*; +import com.oracle.graal.nodes.extended.*; import com.oracle.graal.nodes.java.*; import com.oracle.graal.nodes.type.*; import com.oracle.graal.nodes.util.*; @@ -175,6 +176,18 @@ } /** + * Determines if any parameter of a given method is annotated with {@link ConstantParameter}. + */ + public static boolean hasConstantParameter(ResolvedJavaMethod method) { + for (ConstantParameter p : MetaUtil.getParameterAnnotations(ConstantParameter.class, method)) { + if (p != null) { + return true; + } + } + return false; + } + + /** * Creates a snippet template. */ public SnippetTemplate(CodeCacheProvider runtime, SnippetTemplate.Key key) { @@ -182,7 +195,7 @@ assert Modifier.isStatic(method.accessFlags()) : "snippet method must be static: " + method; Signature signature = method.signature(); - // Copy snippet graph, replacing @Constant parameters with given arguments + // Copy snippet graph, replacing constant parameters with given arguments StructuredGraph snippetGraph = (StructuredGraph) method.compilerStorage().get(Graph.class); StructuredGraph snippetCopy = new StructuredGraph(snippetGraph.name, snippetGraph.method()); IdentityHashMap<Node, Node> replacements = new IdentityHashMap<>(); @@ -201,7 +214,8 @@ replacements.put(snippetGraph.getLocal(i), ConstantNode.forConstant(Constant.forBoxed(kind, arg), runtime, snippetCopy)); } else { Parameter p = MetaUtil.getParameterAnnotation(Parameter.class, i, method); - assert p != null : method + ": parameter " + i + " must be annotated with either @Constant or @Parameter"; + assert p != null : method + ": parameter " + i + " must be annotated with either @" + ConstantParameter.class.getSimpleName() + + " or @" + Parameter.class.getSimpleName(); String name = p.value(); if (p.multiple()) { Object multiple = key.get(name); @@ -219,6 +233,9 @@ Debug.dump(snippetCopy, "Before specialization"); if (!replacements.isEmpty()) { + // Do deferred intrinsification of node intrinsics + new SnippetIntrinsificationPhase(runtime, new BoxingMethodPool(runtime), false).apply(snippetCopy); + new CanonicalizerPhase(null, runtime, null, 0, null).apply(snippetCopy); } @@ -386,6 +403,7 @@ replacements.put((LocalNode) parameter, (ValueNode) argument); } else { Kind kind = ((LocalNode) parameter).kind(); + assert argument != null || kind.isObject() : this + " cannot accept null for non-object parameter named " + name; Constant constant = Constant.forBoxed(kind, argument); replacements.put((LocalNode) parameter, ConstantNode.forConstant(constant, runtime, replaceeGraph)); } @@ -478,10 +496,10 @@ sep = ", "; if (value instanceof LocalNode) { LocalNode local = (LocalNode) value; - buf.append(local.kind().name()).append(' ').append(name); + buf.append(local.kind().javaName).append(' ').append(name); } else { LocalNode[] locals = (LocalNode[]) value; - String kind = locals.length == 0 ? "?" : locals[0].kind().name(); + String kind = locals.length == 0 ? "?" : locals[0].kind().javaName; buf.append(kind).append('[').append(locals.length).append("] ").append(name); } }
--- a/graal/com.oracle.graal.snippets/src/com/oracle/graal/snippets/SnippetVerificationPhase.java Mon Jul 09 14:15:55 2012 +0200 +++ b/graal/com.oracle.graal.snippets/src/com/oracle/graal/snippets/SnippetVerificationPhase.java Mon Jul 09 14:22:22 2012 +0200 @@ -31,6 +31,7 @@ import com.oracle.graal.graph.*; import com.oracle.graal.graph.Node.NodeIntrinsic; import com.oracle.graal.nodes.*; +import com.oracle.graal.nodes.calc.*; import com.oracle.graal.nodes.java.*; import com.oracle.graal.nodes.util.*; import com.oracle.graal.snippets.Word.*; @@ -87,6 +88,11 @@ argc++; } } + } else if (usage instanceof ObjectEqualsNode) { + ObjectEqualsNode compare = (ObjectEqualsNode) usage; + if (compare.x() == node || compare.y() == node) { + verify(isWord(compare.x()) == isWord(compare.y()), node, compare.usages().first(), "cannot mixed word and now-word type in use of '==' or '!='"); + } } else if (usage instanceof ArrayLengthNode) { verify(!isWord(node) || ((ArrayLengthNode) usage).array() != node, node, usage, "cannot get array length from word value"); } else if (usage instanceof PhiNode) {
--- a/graal/com.oracle.graal.snippets/src/com/oracle/graal/snippets/WordTypeRewriterPhase.java Mon Jul 09 14:15:55 2012 +0200 +++ b/graal/com.oracle.graal.snippets/src/com/oracle/graal/snippets/WordTypeRewriterPhase.java Mon Jul 09 14:22:22 2012 +0200 @@ -68,6 +68,17 @@ } } + // Replace ObjectEqualsNodes with IntegerEqualsNodes where the values being compared are words + for (ObjectEqualsNode objectEqualsNode : graph.getNodes().filter(ObjectEqualsNode.class).snapshot()) { + ValueNode x = objectEqualsNode.x(); + ValueNode y = objectEqualsNode.y(); + if (x.kind() == wordKind || y.kind() == wordKind) { + assert x.kind() == wordKind; + assert y.kind() == wordKind; + graph.replaceFloating(objectEqualsNode, graph.unique(new IntegerEqualsNode(x, y))); + } + } + for (MethodCallTargetNode callTargetNode : graph.getNodes(MethodCallTargetNode.class).snapshot()) { ResolvedJavaMethod targetMethod = callTargetNode.targetMethod(); Operation operation = targetMethod.getAnnotation(Word.Operation.class); @@ -188,7 +199,7 @@ ValueNode a = mirror ? right : left; ValueNode b = mirror ? left : right; - MaterializeNode materialize = MaterializeNode.create(graph.unique(new IntegerBelowThanNode(a, b)), graph); + MaterializeNode materialize = MaterializeNode.create(graph.unique(new IntegerBelowThanNode(a, b))); ValueNode op; if (condition.canonicalNegate()) {
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.snippets/src/com/oracle/graal/snippets/nodes/DirectObjectStoreNode.java Mon Jul 09 14:22:22 2012 +0200 @@ -0,0 +1,80 @@ +/* + * Copyright (c) 2012, 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. + */ +package com.oracle.graal.snippets.nodes; + +import com.oracle.graal.nodes.*; +import com.oracle.graal.nodes.extended.*; +import com.oracle.graal.nodes.spi.*; +import com.oracle.graal.nodes.type.*; +import com.oracle.graal.snippets.*; + +/** + * A special purpose store node that differs from {@link UnsafeStoreNode} in that + * it is not a {@link StateSplit} and does not include a write barrier. + */ +public class DirectObjectStoreNode extends FixedWithNextNode implements Lowerable { + @Input private ValueNode object; + @Input private ValueNode value; + @Input private ValueNode offset; + private final int displacement; + + public DirectObjectStoreNode(ValueNode object, int displacement, ValueNode offset, ValueNode value) { + super(StampFactory.forVoid()); + this.object = object; + this.value = value; + this.offset = offset; + this.displacement = displacement; + } + + @SuppressWarnings("unused") + @NodeIntrinsic + public static void storeObject(Object obj, @ConstantNodeParameter int displacement, long offset, Object value) { + throw new UnsupportedOperationException(); + } + + @SuppressWarnings("unused") + @NodeIntrinsic + public static void storeLong(Object obj, @ConstantNodeParameter int displacement, long offset, long value) { + throw new UnsupportedOperationException(); + } + + @SuppressWarnings("unused") + @NodeIntrinsic + public static void storeWord(Object obj, @ConstantNodeParameter int displacement, long offset, Word value) { + throw new UnsupportedOperationException(); + } + + @SuppressWarnings("unused") + @NodeIntrinsic + public static void storeInt(Object obj, @ConstantNodeParameter int displacement, long offset, int value) { + throw new UnsupportedOperationException(); + } + + @Override + public void lower(LoweringTool tool) { + StructuredGraph graph = (StructuredGraph) this.graph(); + IndexedLocationNode location = IndexedLocationNode.create(LocationNode.ANY_LOCATION, value.kind(), displacement, offset, graph, false); + WriteNode write = graph.add(new WriteNode(object, value, location)); + graph.replaceFixedWithFixed(this, write); + } +}
--- a/graal/com.oracle.graal.tests/src/com/oracle/graal/compiler/tests/CheckCastTest.java Mon Jul 09 14:15:55 2012 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,192 +0,0 @@ -/* - * Copyright (c) 2011, 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. - */ -package com.oracle.graal.compiler.tests; - -import org.junit.*; - -import com.oracle.graal.api.meta.*; -import com.oracle.graal.nodes.*; -import com.oracle.graal.nodes.java.*; - -/** - * Tests the implementation of checkcast, allowing profiling information to - * be manually specified. - */ -public class CheckCastTest extends TypeCheckTest { - - /** - * Enables making the target type "unknown" at compile time. - */ - boolean unknown; - - @Override - protected void replaceProfile(StructuredGraph graph, JavaTypeProfile profile) { - CheckCastNode ccn = graph.getNodes(CheckCastNode.class).first(); - if (ccn != null) { - ResolvedJavaType targetClass = unknown ? null : ccn.targetClass(); - CheckCastNode ccnNew = graph.add(new CheckCastNode(ccn.targetClassInstruction(), targetClass, ccn.object(), profile)); - graph.replaceFixedWithFixed(ccn, ccnNew); - } - unknown = false; - } - - @Override - protected void test(String name, JavaTypeProfile profile, Object... args) { - super.test(name, profile, args); - unknown = true; - super.test(name, profile, args); - } - - @Test - public void test1() { - test("asNumber", profile(), 111); - test("asNumber", profile(Integer.class), 111); - test("asNumber", profile(Long.class, Short.class), 111); - test("asNumberExt", profile(), 111); - test("asNumberExt", profile(Integer.class), 111); - test("asNumberExt", profile(Long.class, Short.class), 111); - } - - @Test - public void test2() { - test("asString", profile(), "111"); - test("asString", profile(String.class), "111"); - test("asString", profile(String.class), "111"); - - final String nullString = null; - test("asString", profile(), nullString); - test("asString", profile(String.class), nullString); - test("asString", profile(String.class), nullString); - - test("asStringExt", profile(), "111"); - test("asStringExt", profile(String.class), "111"); - test("asStringExt", profile(String.class), "111"); - } - - @Test - public void test3() { - test("asNumber", profile(), "111"); - } - - @Test - public void test4() { - test("asString", profile(String.class), 111); - } - - @Test - public void test5() { - test("asNumberExt", profile(), "111"); - } - - @Test - public void test6() { - test("asStringExt", profile(String.class), 111); - } - - @Test - public void test7() { - Throwable throwable = new Exception(); - test("asThrowable", profile(), throwable); - test("asThrowable", profile(Throwable.class), throwable); - test("asThrowable", profile(Exception.class, Error.class), throwable); - } - - @Test - public void test8() { - test("arrayFill", profile(), new Object[100], "111"); - } - - public static Number asNumber(Object o) { - return (Number) o; - } - - public static String asString(Object o) { - return (String) o; - } - - public static Throwable asThrowable(Object o) { - return (Throwable) o; - } - - public static ValueNode asValueNode(Object o) { - return (ValueNode) o; - } - - public static Number asNumberExt(Object o) { - Number n = (Number) o; - return n.intValue() + 10; - } - - public static String asStringExt(Object o) { - String s = (String) o; - return "#" + s; - } - - public static Object[] arrayFill(Object[] arr, Object value) { - for (int i = 0; i < arr.length; i++) { - arr[i] = value; - } - return arr; - } - - static class Depth1 implements Cloneable {} - static class Depth2 extends Depth1 {} - static class Depth3 extends Depth2 {} - static class Depth4 extends Depth3 {} - static class Depth5 extends Depth4 {} - static class Depth6 extends Depth5 {} - static class Depth7 extends Depth6 {} - static class Depth8 extends Depth7 {} - static class Depth9 extends Depth8 {} - static class Depth10 extends Depth9 {} - static class Depth11 extends Depth10 {} - static class Depth12 extends Depth11 {} - static class Depth13 extends Depth12 {} - static class Depth14 extends Depth12 {} - - public static Depth12 asDepth12(Object o) { - return (Depth12) o; - } - - public static Depth12[][] asDepth12Arr(Object o) { - return (Depth12[][]) o; - } - - public static Cloneable asCloneable(Object o) { - return (Cloneable) o; - } - - @Test - public void test9() { - Object o = new Depth13(); - test("asDepth12", profile(), o); - test("asDepth12", profile(Depth13.class), o); - test("asDepth12", profile(Depth13.class, Depth14.class), o); - } - - @Test - public void test10() { - Object o = new Depth13[3][]; - test("asDepth12Arr", profile(), o); - } -}
--- a/graal/com.oracle.graal.tests/src/com/oracle/graal/compiler/tests/GraalCompilerTest.java Mon Jul 09 14:15:55 2012 +0200 +++ b/graal/com.oracle.graal.tests/src/com/oracle/graal/compiler/tests/GraalCompilerTest.java Mon Jul 09 14:22:22 2012 +0200 @@ -53,7 +53,7 @@ * <li>Assert that the transformed graph is equal to an expected graph.</li> * </ol> * <p> - * See {@link InvokeTest} as an example. + * See {@link InvokeHintsTest} as an example. * <p> * The tests can be run in Eclipse with the "Compiler Unit Test" Eclipse * launch configuration found in the top level of this project or by @@ -62,10 +62,12 @@ public abstract class GraalCompilerTest { protected final GraalCodeCacheProvider runtime; + protected final GraalCompiler graalCompiler; public GraalCompilerTest() { Debug.enable(); this.runtime = Graal.getRuntime().getCapability(GraalCodeCacheProvider.class); + this.graalCompiler = Graal.getRuntime().getCapability(GraalCompiler.class); } protected void assertEquals(StructuredGraph expected, StructuredGraph graph) { @@ -198,6 +200,16 @@ } /** + * Can be overridden to modify the compilation phases applied for a test. + * + * @param method the method being compiled + * @param graph the graph being compiled + * @param phasePlan the phase plan to be edited + */ + protected void editPhasePlan(ResolvedJavaMethod method, StructuredGraph graph, PhasePlan phasePlan) { + } + + /** * Gets installed code for a given method and graph, compiling it first if necessary. * * @param forceCompile specifies whether to ignore any previous code cached for the (method, key) pair @@ -211,24 +223,27 @@ } InstalledCode installedCode = Debug.scope("Compiling", new DebugDumpScope(String.valueOf(compilationId++), true), new Callable<InstalledCode>() { public InstalledCode call() throws Exception { - CompilationResult targetMethod = runtime.compile(method, graph); - return addMethod(method, targetMethod); + PhasePlan phasePlan = new PhasePlan(); + GraphBuilderPhase graphBuilderPhase = new GraphBuilderPhase(runtime, GraphBuilderConfiguration.getDefault(), OptimisticOptimizations.ALL); + phasePlan.addPhase(PhasePosition.AFTER_PARSING, graphBuilderPhase); + editPhasePlan(method, graph, phasePlan); + CompilationResult compResult = graalCompiler.compileMethod(method, graph, -1, null, phasePlan, OptimisticOptimizations.ALL); + return addMethod(method, compResult); } }); cache.put(method, installedCode); return installedCode; } - protected InstalledCode addMethod(final ResolvedJavaMethod method, final CompilationResult tm) { - GraalCompiler graalCompiler = Graal.getRuntime().getCapability(GraalCompiler.class); + protected InstalledCode addMethod(final ResolvedJavaMethod method, final CompilationResult compResult) { assert graalCompiler != null; return Debug.scope("CodeInstall", new Object[] {graalCompiler, method}, new Callable<InstalledCode>() { @Override public InstalledCode call() throws Exception { final CodeInfo[] info = Debug.isDumpEnabled() ? new CodeInfo[1] : null; - InstalledCode installedMethod = runtime.addMethod(method, tm, info); + InstalledCode installedMethod = runtime.addMethod(method, compResult, info); if (info != null) { - Debug.dump(new Object[] {tm, info[0]}, "After code installation"); + Debug.dump(new Object[] {compResult, info[0]}, "After code installation"); } return installedMethod; }
--- a/graal/com.oracle.graal.tests/src/com/oracle/graal/compiler/tests/InstanceOfTest.java Mon Jul 09 14:15:55 2012 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,146 +0,0 @@ -/* - * Copyright (c) 2011, 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. - */ -package com.oracle.graal.compiler.tests; - -import java.util.*; - -import org.junit.*; - -import com.oracle.graal.api.meta.*; -import com.oracle.graal.nodes.*; -import com.oracle.graal.nodes.java.*; - -/** - * Tests the implementation of instanceof, allowing profiling information to - * be manually specified. - */ -public class InstanceOfTest extends TypeCheckTest { - - @Override - protected void replaceProfile(StructuredGraph graph, JavaTypeProfile profile) { - InstanceOfNode ion = graph.getNodes().filter(InstanceOfNode.class).first(); - if (ion != null) { - InstanceOfNode ionNew = graph.add(new InstanceOfNode(ion.targetClassInstruction(), ion.targetClass(), ion.object(), profile)); - graph.replaceFloating(ion, ionNew); - } - } - - @Test - public void test1() { - test("isString", profile(), "object"); - test("isString", profile(String.class), "object"); - - test("isString", profile(), Object.class); - test("isString", profile(String.class), Object.class); - } - - @Test - public void test2() { - test("isStringInt", profile(), "object"); - test("isStringInt", profile(String.class), "object"); - - test("isStringInt", profile(), Object.class); - test("isStringInt", profile(String.class), Object.class); - } - - @Test - public void test3() { - Throwable throwable = new Exception(); - test("isThrowable", profile(), throwable); - test("isThrowable", profile(Throwable.class), throwable); - test("isThrowable", profile(Exception.class, Error.class), throwable); - - test("isThrowable", profile(), Object.class); - test("isThrowable", profile(Throwable.class), Object.class); - test("isThrowable", profile(Exception.class, Error.class), Object.class); - } - - @Test - public void test4() { - Throwable throwable = new Exception(); - test("isThrowableInt", profile(), throwable); - test("isThrowableInt", profile(Throwable.class), throwable); - test("isThrowableInt", profile(Exception.class, Error.class), throwable); - - test("isThrowableInt", profile(), Object.class); - test("isThrowableInt", profile(Throwable.class), Object.class); - test("isThrowableInt", profile(Exception.class, Error.class), Object.class); - } - - @Test - public void test5() { - Map map = new HashMap<>(); - test("isMap", profile(), map); - test("isMap", profile(HashMap.class), map); - test("isMap", profile(TreeMap.class, HashMap.class), map); - - test("isMap", profile(), Object.class); - test("isMap", profile(HashMap.class), Object.class); - test("isMap", profile(TreeMap.class, HashMap.class), Object.class); - } - - @Test - public void test6() { - Map map = new HashMap<>(); - test("isMapInt", profile(), map); - test("isMapInt", profile(HashMap.class), map); - test("isMapInt", profile(TreeMap.class, HashMap.class), map); - - test("isMapInt", profile(), Object.class); - test("isMapInt", profile(HashMap.class), Object.class); - test("isMapInt", profile(TreeMap.class, HashMap.class), Object.class); - } - - public static boolean isString(Object o) { - return o instanceof String; - } - - public static int isStringInt(Object o) { - if (o instanceof String) { - return 1; - } - return 0; - } - - public static boolean isThrowable(Object o) { - return o instanceof Throwable; - } - - public static int isThrowableInt(Object o) { - if (o instanceof Throwable) { - return 1; - } - return 0; - } - - public static boolean isMap(Object o) { - return o instanceof Map; - } - - public static int isMapInt(Object o) { - if (o instanceof Map) { - return 1; - } - return 0; - } -}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.tests/src/com/oracle/graal/compiler/tests/InvokeHintsTest.java Mon Jul 09 14:22:22 2012 +0200 @@ -0,0 +1,82 @@ +/* + * Copyright (c) 2011, 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. + */ +package com.oracle.graal.compiler.tests; + +import java.util.*; + +import org.junit.*; + +import com.oracle.graal.compiler.*; +import com.oracle.graal.compiler.phases.*; +import com.oracle.graal.nodes.*; + +public class InvokeHintsTest extends GraalCompilerTest { + + private static final String REFERENCE_SNIPPET = "referenceSnippet"; + + public static int const1() { + return 1; + } + + public static int const7() { + return 7; + } + + @SuppressWarnings("all") + public static int referenceSnippet() { + return 7; + } + + @Test + public void test1() { + test("test1Snippet"); + } + + @SuppressWarnings("all") + public static int test1Snippet() { + return const7(); + } + + @Test + public void test2() { + test("test2Snippet"); + } + + @SuppressWarnings("all") + public static int test2Snippet() { + return const1() + const1() + const1() + const1() + const1() + const1() + const1(); + } + + private void test(String snippet) { + StructuredGraph graph = parse(snippet); + Collection<Invoke> hints = new ArrayList<>(); + for (Invoke invoke : graph.getInvokes()) { + hints.add(invoke); + } + new InliningPhase(null, runtime(), hints, null, null, getDefaultPhasePlan(), OptimisticOptimizations.ALL).apply(graph); + new CanonicalizerPhase(null, runtime(), null).apply(graph); + new DeadCodeEliminationPhase().apply(graph); + StructuredGraph referenceGraph = parse(REFERENCE_SNIPPET); + assertEquals(referenceGraph, graph); + } +}
--- a/graal/com.oracle.graal.tests/src/com/oracle/graal/compiler/tests/InvokeTest.java Mon Jul 09 14:15:55 2012 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,87 +0,0 @@ -/* - * Copyright (c) 2011, 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. - */ -package com.oracle.graal.compiler.tests; - -import java.util.*; - -import org.junit.*; - -import com.oracle.graal.compiler.*; -import com.oracle.graal.compiler.phases.*; -import com.oracle.graal.nodes.*; - -/** - * In the following tests, the usages of local variable "a" are replaced with the integer constant 0. - * Then canonicalization is applied and it is verified that the resulting graph is equal to the - * graph of the method that just has a "return 1" statement in it. - */ -public class InvokeTest extends GraalCompilerTest { - - private static final String REFERENCE_SNIPPET = "referenceSnippet"; - - public static int const1() { - return 1; - } - - public static int const7() { - return 7; - } - - @SuppressWarnings("all") - public static int referenceSnippet() { - return 7; - } - - @Test - public void test1() { - test("test1Snippet"); - } - - @SuppressWarnings("all") - public static int test1Snippet() { - return const7(); - } - - @Test - public void test2() { - test("test2Snippet"); - } - - @SuppressWarnings("all") - public static int test2Snippet() { - return const1() + const1() + const1() + const1() + const1() + const1() + const1(); - } - - private void test(String snippet) { - StructuredGraph graph = parse(snippet); - Collection<Invoke> hints = new ArrayList<>(); - for (Invoke invoke : graph.getInvokes()) { - hints.add(invoke); - } - new InliningPhase(null, runtime(), hints, null, null, getDefaultPhasePlan(), OptimisticOptimizations.ALL).apply(graph); - new CanonicalizerPhase(null, runtime(), null).apply(graph); - new DeadCodeEliminationPhase().apply(graph); - StructuredGraph referenceGraph = parse(REFERENCE_SNIPPET); - assertEquals(referenceGraph, graph); - } -}
--- a/graal/com.oracle.graal.tests/src/com/oracle/graal/compiler/tests/NewInstanceTest.java Mon Jul 09 14:15:55 2012 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,188 +0,0 @@ -/* - * Copyright (c) 2011, 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. - */ -package com.oracle.graal.compiler.tests; - -import java.util.*; - -import org.junit.*; - -/** - * Tests the implementation of {@code NEW}. - */ -public class NewInstanceTest extends GraalCompilerTest { - - @Override - protected void assertEquals(Object expected, Object actual) { - Assert.assertTrue(expected != null); - Assert.assertTrue(actual != null); - super.assertEquals(expected.getClass(), actual.getClass()); - if (expected.getClass() != Object.class) { - try { - expected.getClass().getDeclaredMethod("equals", Object.class); - super.assertEquals(expected, actual); - } catch (Exception e) { - } - } - } - - @Test - public void test1() { - test("newObject"); - test("newBigObject"); - test("newSomeObject"); - test("newEmptyString"); - test("newString", "value"); - test("newHashMap", 31); - test("newRegression", true); - } - - public static Object newObject() { - return new Object(); - } - - public static BigObject newBigObject() { - return new BigObject(); - } - - public static SomeObject newSomeObject() { - return new SomeObject(); - } - - public static String newEmptyString() { - return new String(); - } - - public static String newString(String value) { - return new String(value); - } - - public static HashMap newHashMap(int initialCapacity) { - return new HashMap(initialCapacity); - } - - static class SomeObject { - String name = "o1"; - HashMap<String, Object> map = new HashMap<>(); - - - public SomeObject() { - map.put(name, this.getClass()); - } - - @Override - public boolean equals(Object obj) { - if (obj instanceof SomeObject) { - SomeObject so = (SomeObject) obj; - return so.name.equals(name) && so.map.equals(map); - } - return false; - } - - @Override - public int hashCode() { - return name.hashCode(); - } - } - - static class BigObject { - Object f01; - Object f02; - Object f03; - Object f04; - Object f05; - Object f06; - Object f07; - Object f08; - Object f09; - Object f10; - Object f12; - Object f13; - Object f14; - Object f15; - Object f16; - Object f17; - Object f18; - Object f19; - Object f20; - Object f21; - Object f22; - Object f23; - Object f24; - Object f25; - Object f26; - Object f27; - Object f28; - Object f29; - Object f30; - Object f31; - Object f32; - Object f33; - Object f34; - Object f35; - Object f36; - Object f37; - Object f38; - Object f39; - Object f40; - Object f41; - Object f42; - Object f43; - Object f44; - Object f45; - } - - /** - * Tests that an earlier bug does not occur. The issue was that the loading of the TLAB - * 'top' and 'end' values was being GVN'ed from each branch of the 'if' statement. - * This meant that the allocated B object in the true branch overwrote the allocated - * array. The cause is that RegisterNode was a floating node and the reads from it - * were UnsafeLoads which are also floating. The fix was to make RegisterNode a fixed - * node (which it should have been in the first place). - */ - public static Object newRegression(boolean condition) { - Object result; - if (condition) { - Object[] arr = {0, 1, 2, 3, 4, 5}; - result = new B(); - for (int i = 0; i < arr.length; ++i) { - // If the bug exists, the values of arr will now be deadbeef values - // and the virtual dispatch will cause a segfault. This can result in - // either a VM crash or a spurious NullPointerException. - if (arr[i].equals(Integer.valueOf(i))) { - return false; - } - } - } else { - result = new B(); - } - return result; - } - - static class B { - long f1 = 0xdeadbeefdeadbe01L; - long f2 = 0xdeadbeefdeadbe02L; - long f3 = 0xdeadbeefdeadbe03L; - long f4 = 0xdeadbeefdeadbe04L; - long f5 = 0xdeadbeefdeadbe05L; - } -}
--- a/graal/com.oracle.graal.tests/src/com/oracle/graal/compiler/tests/TypeCheckTest.java Mon Jul 09 14:15:55 2012 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,68 +0,0 @@ -/* - * Copyright (c) 2011, 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. - */ -package com.oracle.graal.compiler.tests; - -import com.oracle.graal.api.meta.*; -import com.oracle.graal.api.meta.JavaTypeProfile.*; -import com.oracle.graal.nodes.*; - -/** - * Base class for checkcast and instanceof test classes. - */ -public abstract class TypeCheckTest extends GraalCompilerTest { - - protected abstract void replaceProfile(StructuredGraph graph, JavaTypeProfile profile); - - protected JavaTypeProfile currentProfile; - - @Override - protected InstalledCode getCode(final ResolvedJavaMethod method, final StructuredGraph graph) { - boolean forceCompile = false; - if (currentProfile != null) { - replaceProfile(graph, currentProfile); - forceCompile = true; - } - return super.getCode(method, graph, forceCompile); - } - - protected JavaTypeProfile profile(Class... types) { - if (types.length == 0) { - return null; - } - ProfiledType[] ptypes = new ProfiledType[types.length]; - for (int i = 0; i < types.length; i++) { - ptypes[i] = new ProfiledType(runtime.getResolvedJavaType(types[i]), 1.0D / types.length); - } - return new JavaTypeProfile(0.0D, ptypes); - } - - protected void test(String name, JavaTypeProfile profile, Object... args) { - assert currentProfile == null; - currentProfile = profile; - try { - super.test(name, args); - } finally { - currentProfile = null; - } - } -}
--- a/graal/com.oracle.max.asm/src/com/oracle/max/asm/target/amd64/AMD64Assembler.java Mon Jul 09 14:15:55 2012 +0200 +++ b/graal/com.oracle.max.asm/src/com/oracle/max/asm/target/amd64/AMD64Assembler.java Mon Jul 09 14:22:22 2012 +0200 @@ -202,8 +202,8 @@ if (base == Register.Frame) { assert frameRegister != null : "cannot use register " + Register.Frame + " in assembler with null register configuration"; base = frameRegister; -// } else if (base == CiRegister.CallerFrame) { -// assert frameRegister != null : "cannot use register " + CiRegister.Frame + " in assembler with null register configuration"; +// } else if (base == Register.CallerFrame) { +// assert frameRegister != null : "cannot use register " + Register.Frame + " in assembler with null register configuration"; // base = frameRegister; // disp += targetMethod.frameSize() + 8; }
--- a/graal/com.oracle.max.cri/src/com/oracle/max/cri/xir/CiXirAssembler.java Mon Jul 09 14:15:55 2012 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,939 +0,0 @@ -/* - * Copyright (c) 2009, 2011, 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. - */ -package com.oracle.max.cri.xir; - -import static com.oracle.max.cri.xir.CiXirAssembler.XirOp.*; - -import java.util.*; - -import com.oracle.graal.api.code.*; -import com.oracle.graal.api.code.Address.*; -import com.oracle.graal.api.meta.*; - -/** - * Represents an assembler that allows a client such as the runtime system to - * create {@link XirTemplate XIR templates}. - */ -public abstract class CiXirAssembler { - - protected XirOperand resultOperand; - protected boolean allocateResultOperand; - - protected final List<XirInstruction> instructions = new ArrayList<>(); - protected final List<XirLabel> labels = new ArrayList<>(5); - protected final List<XirParameter> parameters = new ArrayList<>(5); - protected final List<XirTemp> temps = new ArrayList<>(5); - protected final List<XirConstant> constants = new ArrayList<>(5); - protected final List<XirMark> marks = new ArrayList<>(5); - - protected int outgoingStackSize = 0; - - /** - * Increases by one for every {@link XirOperand operand} created. - */ - protected int variableCount; - - /** - * Marks the assembly complete. - */ - protected boolean finished = true; - - protected final TargetDescription target; - - public CiXirAssembler(TargetDescription target) { - this.target = target; - } - - public static class RuntimeCallInformation { - public final Object target; - public final boolean useInfoAfter; - - public RuntimeCallInformation(Object target, boolean useInfoAfter) { - this.target = target; - this.useInfoAfter = useInfoAfter; - } - } - - /** - * Represents additional address calculation information. - */ - public static final class AddressAccessInformation { - - /** - * The scaling factor for the scaled-index part of an address computation. - */ - public final Scale scale; - - /** - * The constant byte-sized displacement part of an address computation. - */ - public final int disp; - - /** - * Determines if the memory access through the address can trap. - */ - public final boolean canTrap; - - private AddressAccessInformation(boolean canTrap) { - this.canTrap = canTrap; - this.scale = Scale.Times1; - this.disp = 0; - } - - private AddressAccessInformation(boolean canTrap, int disp) { - this.canTrap = canTrap; - this.scale = Scale.Times1; - this.disp = disp; - } - - private AddressAccessInformation(boolean canTrap, int disp, Scale scale) { - this.canTrap = canTrap; - this.scale = scale; - this.disp = disp; - } - } - - /** - * A label that is the target of a control flow instruction. - */ - public static final class XirLabel { - public static final String TrueSuccessor = "TrueSuccessor"; - public static final String FalseSuccessor = "FalseSuccessor"; - public final String name; - public final int index; - /** - * If {@code true} the label is to an instruction in the fast path sequence, otherwise to the slow path. - */ - public final boolean inline; - - private XirLabel(String name, int index, boolean inline) { - this.name = name; - this.index = index; - this.inline = inline; - } - - @Override - public String toString() { - return name; - } - } - - /** - * Tagging interface that indicates that an {@link XirOperand} is a constant. - */ - public interface XirConstantOperand { - int getIndex(); - } - - public static final XirOperand VOID = null; - - /** - * Operands for {@link XirInstruction instructions}. - * There are three basic variants, {@link XirConstant constant}, {@link XirParameter parameter} and {@link XirTemp}. - */ - public abstract static class XirOperand { - - public final Kind kind; - - /** - * Unique id in range {@code 0} to {@link #variableCount variableCount - 1}. - */ - public final int index; - - /** - * Value whose {@link #toString()} method provides a name for this operand. - */ - public final Object name; - - public XirOperand(CiXirAssembler asm, Object name, Kind kind) { - this.kind = kind; - this.name = name; - this.index = asm.variableCount++; - } - - @Override - public String toString() { - return String.valueOf(name); - } - - public String detailedToString() { - - StringBuffer sb = new StringBuffer(); - - sb.append(name); - sb.append('$'); - sb.append(kind.typeChar); - return sb.toString(); - } - } - - /** - * Parameters to {@link XirTemplate templates}. - */ - public static class XirParameter extends XirOperand { - /** - * Unique id in range {@code 0} to {@code parameters.Size() - 1}. - */ - public final int parameterIndex; - - public final boolean canBeConstant; - - XirParameter(CiXirAssembler asm, String name, Kind kind, boolean canBeConstant) { - super(asm, name, kind); - this.parameterIndex = asm.parameters.size(); - this.canBeConstant = canBeConstant; - asm.parameters.add(this); - } - - } - - public static class XirConstantParameter extends XirParameter implements XirConstantOperand { - XirConstantParameter(CiXirAssembler asm, String name, Kind kind) { - super(asm, name, kind, true); - } - - public int getIndex() { - return index; - } - } - - public static class XirVariableParameter extends XirParameter { - XirVariableParameter(CiXirAssembler asm, String name, Kind kind, boolean canBeConstant) { - super(asm, name, kind, canBeConstant); - } - } - - public static class XirConstant extends XirOperand implements XirConstantOperand { - public final Constant value; - - XirConstant(CiXirAssembler asm, Constant value) { - super(asm, value, value.kind); - this.value = value; - } - - public int getIndex() { - return index; - } - } - - public static class XirTemp extends XirOperand { - public final boolean reserve; - - XirTemp(CiXirAssembler asm, String name, Kind kind, boolean reserve) { - super(asm, name, kind); - this.reserve = reserve; - } - } - - public static class XirRegister extends XirTemp { - public final Value register; - - XirRegister(CiXirAssembler asm, String name, RegisterValue register, boolean reserve) { - super(asm, name, register.kind, reserve); - this.register = register; - } - } - - /** - * Start a new assembly with no initial {@link #resultOperand result operand}. - */ - public void restart() { - reset(); - resultOperand = null; - } - - /** - * Start a new assembly with a {@link #resultOperand result operand} of type {@code kind}. - * @param kind the result kind - * @return an {@code XirOperand} for the result operand - */ - public XirOperand restart(Kind kind) { - reset(); - resultOperand = new XirTemp(this, "result", kind, true); - allocateResultOperand = true; - return resultOperand; - } - - /** - * Reset the state of the class to the initial conditions to facilitate a new assembly. - */ - private void reset() { - assert finished : "must be finished before!"; - variableCount = 0; - allocateResultOperand = false; - finished = false; - instructions.clear(); - labels.clear(); - parameters.clear(); - temps.clear(); - constants.clear(); - marks.clear(); - outgoingStackSize = 0; - } - - /** - * Represents an XIR instruction, characterized by an {@link XirOp operation}, a {@link Kind kind}, an optional {@link XirOperand result}, a variable number of {@link XirOperand arguments}, - * and some optional instruction-specific state. The {@link #x}, {@link #y} and {@link #z} methods are convenient ways to access the first, second and third - * arguments, respectively. Only {@link XirOp#CallRuntime} instructions can have more than three arguments. - * - */ - public static final class XirInstruction { - /** - * The {@link Kind kind} of values the instruction operates on. - */ - public final Kind kind; - /** - * The {@link XirOp operation}. - */ - public final XirOp op; - /** - * The result, if any. - */ - public final XirOperand result; - /** - * The arguments. - */ - public final XirOperand[] arguments; - /** - * Arbitrary additional data associated with the instruction. - */ - public final Object extra; - - public XirInstruction(Kind kind, XirOp op, XirOperand result, XirOperand... arguments) { - this(kind, null, op, result, arguments); - } - - public XirInstruction(Kind kind, Object extra, XirOp op, XirOperand result, XirOperand... arguments) { - this.extra = extra; - this.kind = kind; - this.op = op; - this.result = result; - this.arguments = arguments; - } - - public XirOperand x() { - assert arguments.length > 0 : "no x operand for this instruction"; - return arguments[0]; - } - - public XirOperand y() { - assert arguments.length > 1 : "no y operand for this instruction"; - return arguments[1]; - } - - public XirOperand z() { - assert arguments.length > 2 : "no z operand for this instruction"; - return arguments[2]; - } - - @Override - public String toString() { - StringBuffer sb = new StringBuffer(); - - if (result != null) { - sb.append(result.toString()); - sb.append(" = "); - } - - sb.append(op.name()); - - if (kind != Kind.Void) { - sb.append('$'); - sb.append(kind.typeChar); - } - - if (arguments != null && arguments.length > 0) { - sb.append("("); - - for (int i = 0; i < arguments.length; i++) { - if (i != 0) { - sb.append(", "); - } - sb.append(arguments[i]); - } - - sb.append(")"); - } - - if (extra != null) { - sb.append(" "); - sb.append(extra); - } - - return sb.toString(); - } - } - - /** - * These marks let the RiXirGenerator mark positions in the generated native code and bring them in relationship with on another. - * This is necessary for code patching, etc. - */ - public static class XirMark { - public final XirMark[] references; - public final Object id; - - // special mark used to refer to the actual call site of an invoke - public static final XirMark CALLSITE = new XirMark(null); - - public XirMark(Object id, XirMark... references) { - this.id = id; - this.references = references; - } - } - - /** - * The set of opcodes for XIR instructions. - * {@link XirInstruction} defines {@code x}, {@code y} and {@code z} as the first, second and third arguments, respectively. - * We use these mnemonics, plus {@code args} for the complete set of arguments, {@code r} for the result, and {@code extra} - * for the instruction-specific extra data, in the opcode specifications. Note that the opcodes that operate on values do not directly - * specify the size (kind) of the data operated on; this is is encoded in {@link XirInstruction#kind}. - * Note: If the instruction kind differs from the argument/result kinds, the behavior is undefined. - * - */ - public enum XirOp { - /** - * Move {@code x} to {@code r}. - */ - Mov, - /** - * Add {@code y} to {@code x} and put the result in {@code r}. - */ - Add, - /** - * Subtract {@code y} from {@code x} and put the result in {@code r}. - */ - Sub, - /** - * Divide {@code y} by {@code x} and put the result in {@code r}. - */ - Div, - /** - * Multiply {@code y} by {@code x} and put the result in {@code r}. - */ - Mul, - /** - * {@code y} modulus {@code x} and put the result in {@code r}. - */ - Mod, - /** - * Shift {@code y} left by {@code x} and put the result in {@code r}. - */ - Shl, - /** - * Arithmetic shift {@code y} right by {@code x} and put the result in {@code r}. - */ - Sar, - /** - * Shift {@code y} right by {@code x} and put the result in {@code r}. - */ - Shr, - /** - * And {@code y} by {@code x} and put the result in {@code r}. - */ - And, - /** - * Or {@code y} by {@code x} and put the result in {@code r}. - */ - Or, - /** - * Exclusive Or {@code y} by {@code x} and put the result in {@code r}. - */ - Xor, - /** - * Null check on {@code x}. - */ - NullCheck, - /** - * Load value at address {@code x} and put the result in {@code r}. - */ - PointerLoad, - /** - * Store {@code y} at address {@code x}. - */ - PointerStore, - /** - * Load value at an effective address defined by base {@code x} and either a scaled index {@code y} plus displacement - * or an offset {@code y} and put the result in {@code r}. - */ - PointerLoadDisp, - /** - * Load an effective address defined by base {@code x} and either a scaled index {@code y} plus displacement - * or an offset {@code y} and put the result in {@code r}. - */ - LoadEffectiveAddress, - /** - * Store {@code z} at address defined by base {@code x} and index {@code y}. - */ - PointerStoreDisp, - /** - * Repeat move from {@code x} to {@code y} using {@code z} words. - */ - RepeatMoveWords, - /** - * Repeat move from {@code x} to {@code y} using {@code z} words. - */ - RepeatMoveBytes, - /** - * Compare value at at address {@code x} with value in {@code y} and store value {@code z} at address {@code x} - * if it was equal to {@code y}. - */ - PointerCAS, - /** - * Call the {@link JavaMethod} defined by {@code extra} with {@code args} and put the result in {@code r}. - */ - CallRuntime, - /** - * Transfer control to the instruction at the {@link XirLabel label} identified by {@code extra}. - */ - Jmp, - /** - * If {@code x == y}, transfer control to the instruction at the {@link XirLabel label} identified by {@code extra}. - */ - Jeq, - /** - * If {@code x != y}, transfer control to the instruction at the {@link XirLabel label} identified by {@code extra}. - */ - Jneq, - /** - * If {@code x > y}, transfer control to the instruction at the {@link XirLabel label} identified by {@code extra}. - */ - Jgt, - /** - * If {@code x >= y}, transfer control to the instruction at the {@link XirLabel label} identified by {@code extra}. - */ - Jgteq, - /** - * If {@code x unsigned >= y}, transfer control to the instruction at the {@link XirLabel label} identified by {@code extra}. - */ - Jugteq, - /** - * If {@code x < y}, transfer control to the instruction at the {@link XirLabel label} identified by {@code extra}. - */ - Jlt, - /** - * If {@code x <= y}, transfer control to the instruction at the {@link XirLabel label} identified by {@code extra}. - */ - Jlteq, - /** - * Decreases the input by one and jumps to the target if the input is not 0. - */ - DecAndJumpNotZero, - /** - * If bit designated by {@code z} at effective address defined by base {@code x} and offset {@code y} - * is set transfer control to the instruction at the {@link XirLabel label} identified by {@code extra}. - */ - Jbset, - /** - * Bind the {@link XirLabel label} identified by {@code extra} to the current instruction and update any references to it. - * A label may be bound more than once to the same location. - */ - Bind, - /** - * Record a safepoint. - */ - Safepoint, - /** - * Pushes a value onto the stack. - */ - Push, - /** - * Pops a value from the stack. - */ - Pop, - /** - * Marks a position in the generated native code. - */ - Mark, - /** - * Load instruction pointer of the next instruction in a destination register. - */ - Here, - /** - * Inserts nop instructions, with the given size in bytes. - */ - Nop, - /** - * This instruction should never be reached, this is useful for debugging purposes. - */ - ShouldNotReachHere - } - - public/*private*/ void append(XirInstruction xirInstruction) { - assert !finished : "no instructions can be added to finished template"; - instructions.add(xirInstruction); - } - - public XirLabel createInlineLabel(String name) { - final XirLabel result = new XirLabel(name, this.labels.size(), true); - labels.add(result); - return result; - } - - public XirLabel createOutOfLineLabel(String name) { - final XirLabel result = new XirLabel(name, this.labels.size(), false); - labels.add(result); - return result; - } - - public void mov(XirOperand result, XirOperand a) { - append(new XirInstruction(result.kind, Mov, result, a)); - } - - public void add(XirOperand result, XirOperand a, XirOperand b) { - append(new XirInstruction(result.kind, Add, result, a, b)); - } - - public void sub(XirOperand result, XirOperand a, XirOperand b) { - append(new XirInstruction(result.kind, Sub, result, a, b)); - } - - public void div(XirOperand result, XirOperand a, XirOperand b) { - append(new XirInstruction(result.kind, Div, result, a, b)); - } - - public void mul(XirOperand result, XirOperand a, XirOperand b) { - append(new XirInstruction(result.kind, Mul, result, a, b)); - } - - public void mod(XirOperand result, XirOperand a, XirOperand b) { - append(new XirInstruction(result.kind, Mod, result, a, b)); - } - - public void shl(XirOperand result, XirOperand a, XirOperand b) { - append(new XirInstruction(result.kind, Shl, result, a, b)); - } - - public void shr(XirOperand result, XirOperand a, XirOperand b) { - append(new XirInstruction(result.kind, Shr, result, a, b)); - } - - public void and(XirOperand result, XirOperand a, XirOperand b) { - append(new XirInstruction(result.kind, And, result, a, b)); - } - - public void or(XirOperand result, XirOperand a, XirOperand b) { - append(new XirInstruction(result.kind, Or, result, a, b)); - } - - public void xor(XirOperand result, XirOperand a, XirOperand b) { - append(new XirInstruction(result.kind, Xor, result, a, b)); - } - - public void nullCheck(XirOperand pointer) { - append(new XirInstruction(Kind.Object, NullCheck, VOID, pointer)); - } - - public void pload(Kind kind, XirOperand result, XirOperand pointer, boolean canTrap) { - append(new XirInstruction(kind, canTrap, PointerLoad, result, pointer)); - } - - public void pstore(Kind kind, XirOperand pointer, XirOperand value, boolean canTrap) { - append(new XirInstruction(kind, canTrap, PointerStore, null, pointer, value)); - } - - public void pload(Kind kind, XirOperand result, XirOperand pointer, XirOperand offset, boolean canTrap) { - append(new XirInstruction(kind, new AddressAccessInformation(canTrap), PointerLoadDisp, result, pointer, offset)); - } - - public void pstore(Kind kind, XirOperand pointer, XirOperand offset, XirOperand value, boolean canTrap) { - append(new XirInstruction(kind, new AddressAccessInformation(canTrap), PointerStoreDisp, VOID, pointer, offset, value)); - } - - public void pload(Kind kind, XirOperand result, XirOperand pointer, XirOperand index, int disp, Scale scale, boolean canTrap) { - append(new XirInstruction(kind, new AddressAccessInformation(canTrap, disp, scale), PointerLoadDisp, result, pointer, index)); - } - - public void lea(XirOperand result, XirOperand pointer, XirOperand index, int disp, Scale scale) { - append(new XirInstruction(target.wordKind, new AddressAccessInformation(false, disp, scale), LoadEffectiveAddress, result, pointer, index)); - } - - public void repmov(XirOperand src, XirOperand dest, XirOperand length) { - append(new XirInstruction(target.wordKind, null, RepeatMoveWords, null, src, dest, length)); - } - - public void here(XirOperand dst) { - append(new XirInstruction(target.wordKind, null, Here, dst)); - } - - public void repmovb(XirOperand src, XirOperand dest, XirOperand length) { - append(new XirInstruction(target.wordKind, null, RepeatMoveBytes, null, src, dest, length)); - } - - public void pstore(Kind kind, XirOperand pointer, XirOperand index, XirOperand value, int disp, Scale scale, boolean canTrap) { - append(new XirInstruction(kind, new AddressAccessInformation(canTrap, disp, scale), PointerStoreDisp, VOID, pointer, index, value)); - } - - public void pcas(Kind kind, XirOperand result, XirOperand pointer, XirOperand newValue, XirOperand oldValue) { - append(new XirInstruction(kind, null, PointerCAS, result, pointer, newValue, oldValue)); - } - - public void jmp(XirLabel l) { - append(new XirInstruction(Kind.Void, l, Jmp, null)); - } - - public void decAndJumpNotZero(XirLabel l, XirOperand val) { - append(new XirInstruction(Kind.Void, l, DecAndJumpNotZero, null, val)); - } - - public void jmpRuntime(Object rt) { - append(new XirInstruction(Kind.Void, rt, Jmp, null)); - } - - public void jeq(XirLabel l, XirOperand a, XirOperand b) { - jcc(Jeq, l, a, b); - } - - private void jcc(XirOp op, XirLabel l, XirOperand a, XirOperand b) { - append(new XirInstruction(Kind.Void, l, op, null, a, b)); - } - - public void jneq(XirLabel l, XirOperand a, XirOperand b) { - jcc(Jneq, l, a, b); - } - - public void jgt(XirLabel l, XirOperand a, XirOperand b) { - jcc(Jgt, l, a, b); - } - - public void jgteq(XirLabel l, XirOperand a, XirOperand b) { - jcc(Jgteq, l, a, b); - } - - public void jugteq(XirLabel l, XirOperand a, XirOperand b) { - jcc(Jugteq, l, a, b); - } - - public void jlt(XirLabel l, XirOperand a, XirOperand b) { - jcc(Jlt, l, a, b); - } - - public void jlteq(XirLabel l, XirOperand a, XirOperand b) { - jcc(Jlteq, l, a, b); - } - - public void jbset(XirLabel l, XirOperand a, XirOperand b, XirOperand c) { - append(new XirInstruction(Kind.Void, l, Jbset, null, a, b, c)); - } - - public void bindInline(XirLabel l) { - assert l.inline; - append(new XirInstruction(Kind.Void, l, Bind, null)); - } - - public void bindOutOfLine(XirLabel l) { - assert !l.inline; - append(new XirInstruction(Kind.Void, l, Bind, null)); - } - - public void safepoint() { - append(new XirInstruction(Kind.Void, null, Safepoint, null)); - } - - public void push(XirOperand value) { - append(new XirInstruction(Kind.Void, Push, VOID, value)); - } - - public void pop(XirOperand result) { - append(new XirInstruction(result.kind, Pop, result)); - } - - public XirMark mark(Object id, XirMark... references) { - XirMark mark = new XirMark(id, references); - marks.add(mark); - append(new XirInstruction(Kind.Void, mark, Mark, null)); - return mark; - } - - public void nop(int size) { - append(new XirInstruction(Kind.Void, size, Nop, null)); - } - - public void shouldNotReachHere() { - append(new XirInstruction(Kind.Void, null, ShouldNotReachHere, null)); - } - - public void shouldNotReachHere(String message) { - append(new XirInstruction(Kind.Void, message, ShouldNotReachHere, null)); - } - - public void callRuntime(Object rt, XirOperand result, XirOperand... args) { - callRuntime(rt, result, false, args); - } - - public void callRuntime(Object rt, XirOperand result, boolean useInfoAfter, XirOperand... args) { - Kind resultKind = result == null ? Kind.Void : result.kind; - append(new XirInstruction(resultKind, new RuntimeCallInformation(rt, useInfoAfter), CallRuntime, result, args)); - } - - /** - * Terminates the assembly, checking invariants, in particular that {@link #resultOperand} is set, and setting {@link #finished} to {@code true}. - */ - private void end() { - assert !finished : "template may only be finished once!"; - assert resultOperand != null : "result operand should be set"; - finished = true; - } - - /** - * Creates an {@link XirVariableParameter variable input parameter} of given name and {@link Kind kind}. - * @param name a name for the parameter - * @param kind the parameter kind - * @return the {@link XirVariableParameter} - */ - public XirVariableParameter createInputParameter(String name, Kind kind, boolean canBeConstant) { - assert !finished; - return new XirVariableParameter(this, name, kind, canBeConstant); - } - - public XirVariableParameter createInputParameter(String name, Kind kind) { - return createInputParameter(name, kind, false); - } - - /** - * Creates an {@link XirConstantParameter constant input parameter} of given name and {@link Kind kind}. - * @param name a name for the parameter - * @param kind the parameter kind - * @return the {@link XirConstantParameter} - */ - public XirConstantParameter createConstantInputParameter(String name, Kind kind) { - assert !finished; - return new XirConstantParameter(this, name, kind); - } - - public XirConstant createConstant(Constant constant) { - assert !finished; - XirConstant temp = new XirConstant(this, constant); - constants.add(temp); - return temp; - } - - public XirOperand createTemp(String name, Kind kind) { - assert !finished; - XirTemp temp = new XirTemp(this, name, kind, true); - temps.add(temp); - return temp; - } - - public XirOperand createRegister(String name, Kind kind, Register register) { - return createRegister(name, kind, register, false); - } - - public XirOperand createRegisterTemp(String name, Kind kind, Register register) { - return createRegister(name, kind, register, true); - } - - private XirOperand createRegister(String name, Kind kind, Register register, boolean reserve) { - assert !finished; - XirRegister fixed = new XirRegister(this, name, register.asValue(kind), reserve); - temps.add(fixed); - return fixed; - } - - public XirParameter getParameter(String name) { - for (XirParameter param : parameters) { - if (param.name.toString().equals(name)) { - return param; - } - } - throw new IllegalArgumentException("no parameter: " + name); - } - - public XirTemp getTemp(String name) { - for (XirTemp temp : temps) { - if (temp.name.toString().equals(name)) { - return temp; - } - } - throw new IllegalArgumentException("no temp: " + name); - } - - public XirConstant i(int v) { - return createConstant(Constant.forInt(v)); - } - - public XirConstant l(long v) { - return createConstant(Constant.forLong(v)); - } - - public XirConstant b(boolean v) { - return createConstant(Constant.forBoolean(v)); - } - - public XirConstant o(Object obj) { - return createConstant(Constant.forObject(obj)); - } - - public void reserveOutgoingStack(int size) { - outgoingStackSize = Math.max(outgoingStackSize, size); - } - - /** - * Finishes the assembly of a non-stub template, providing the {@link #resultOperand} and constructs the {@link XirTemplate}. - * @param result the {@link XirOperand} to be set as the {@link #resultOperand} - * @param name the name of the template - * @return the generated template - */ - public XirTemplate finishTemplate(XirOperand result, String name) { - assert this.resultOperand == null; - assert result != null; - this.resultOperand = result; - final XirTemplate template = buildTemplate(name, false); - end(); - return template; - } - - /** - * Finishes the assembly of a non-stub template and constructs the {@link XirTemplate}. - * @param name the name of the template - * @return the generated template - */ - public XirTemplate finishTemplate(String name) { - final XirTemplate template = buildTemplate(name, false); - end(); - return template; - } - - /** - * Finishes the assembly of a {@link XirTemplate.GlobalFlags#GLOBAL_STUB stub} and constructs the {@link XirTemplate}. - * @param name the name of the template - * @return the generated template - */ - public XirTemplate finishStub(String name) { - final XirTemplate template = buildTemplate(name, true); - end(); - return template; - } - - /** - * Builds the {@link XirTemplate} from the assembly state in this object. - * The actual assembly is dependent on the target architecture and implemented - * in a concrete subclass. - * @param name the name of the template - * @param isStub {@code true} if the template represents a {@link XirTemplate.GlobalFlags#GLOBAL_STUB stub} - * @return the generated template - */ - protected abstract XirTemplate buildTemplate(String name, boolean isStub); - - public abstract CiXirAssembler copy(); - -}
--- a/graal/com.oracle.max.cri/src/com/oracle/max/cri/xir/RiXirGenerator.java Mon Jul 09 14:15:55 2012 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,76 +0,0 @@ -/* - * Copyright (c) 2009, 2011, 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. - */ -package com.oracle.max.cri.xir; - -import com.oracle.graal.api.meta.*; -import com.oracle.graal.api.meta.JavaType.*; - -/** - * Represents the interface through which the compiler requests the XIR for a given bytecode from the runtime system. - */ -public interface RiXirGenerator { - - XirSnippet genInvokeInterface(XirSite site, XirArgument receiver, JavaMethod method); - - XirSnippet genInvokeVirtual(XirSite site, XirArgument receiver, JavaMethod method, boolean megamorph); - - XirSnippet genInvokeSpecial(XirSite site, XirArgument receiver, JavaMethod method); - - XirSnippet genInvokeStatic(XirSite site, JavaMethod method); - - XirSnippet genMonitorEnter(XirSite site, XirArgument receiver, XirArgument lockAddress); - - XirSnippet genMonitorExit(XirSite site, XirArgument receiver, XirArgument lockAddress); - - XirSnippet genNewInstance(XirSite site, JavaType type); - - XirSnippet genNewArray(XirSite site, XirArgument length, Kind elementKind, JavaType componentType, JavaType arrayType); - - XirSnippet genNewMultiArray(XirSite site, XirArgument[] lengths, JavaType type); - - XirSnippet genCheckCast(XirSite site, XirArgument receiver, XirArgument hub, ResolvedJavaType type, JavaTypeProfile profile); - - XirSnippet genInstanceOf(XirSite site, XirArgument receiver, XirArgument hub, ResolvedJavaType type, JavaTypeProfile profile); - - XirSnippet genMaterializeInstanceOf(XirSite site, XirArgument receiver, XirArgument hub, XirArgument trueValue, XirArgument falseValue, ResolvedJavaType type, JavaTypeProfile profile); - - /** - * Generates code that checks that the {@linkplain Representation#ObjectHub hub} of - * an object is identical to a given hub constant. In pseudo code: - * <pre> - * if (object.getHub() != hub) { - * jump(falseSuccessor) - * } - * </pre> - * This snippet should only be used when the object is guaranteed not to be null. - */ - XirSnippet genTypeBranch(XirSite site, XirArgument thisHub, XirArgument otherHub, JavaType type); - - /** - * Initializes the XIR generator for the given XIR assembler. - * - * @param asm the XIR assembler - */ - void initialize(CiXirAssembler asm); - -}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.max.cri/src/com/oracle/max/cri/xir/XirAssembler.java Mon Jul 09 14:22:22 2012 +0200 @@ -0,0 +1,939 @@ +/* + * Copyright (c) 2009, 2011, 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. + */ +package com.oracle.max.cri.xir; + +import static com.oracle.max.cri.xir.XirAssembler.XirOp.*; + +import java.util.*; + +import com.oracle.graal.api.code.*; +import com.oracle.graal.api.code.Address.*; +import com.oracle.graal.api.meta.*; + +/** + * Represents an assembler that allows a client such as the runtime system to + * create {@link XirTemplate XIR templates}. + */ +public abstract class XirAssembler { + + protected XirOperand resultOperand; + protected boolean allocateResultOperand; + + protected final List<XirInstruction> instructions = new ArrayList<>(); + protected final List<XirLabel> labels = new ArrayList<>(5); + protected final List<XirParameter> parameters = new ArrayList<>(5); + protected final List<XirTemp> temps = new ArrayList<>(5); + protected final List<XirConstant> constants = new ArrayList<>(5); + protected final List<XirMark> marks = new ArrayList<>(5); + + protected int outgoingStackSize = 0; + + /** + * Increases by one for every {@link XirOperand operand} created. + */ + protected int variableCount; + + /** + * Marks the assembly complete. + */ + protected boolean finished = true; + + protected final TargetDescription target; + + public XirAssembler(TargetDescription target) { + this.target = target; + } + + public static class RuntimeCallInformation { + public final Object target; + public final boolean useInfoAfter; + + public RuntimeCallInformation(Object target, boolean useInfoAfter) { + this.target = target; + this.useInfoAfter = useInfoAfter; + } + } + + /** + * Represents additional address calculation information. + */ + public static final class AddressAccessInformation { + + /** + * The scaling factor for the scaled-index part of an address computation. + */ + public final Scale scale; + + /** + * The constant byte-sized displacement part of an address computation. + */ + public final int disp; + + /** + * Determines if the memory access through the address can trap. + */ + public final boolean canTrap; + + private AddressAccessInformation(boolean canTrap) { + this.canTrap = canTrap; + this.scale = Scale.Times1; + this.disp = 0; + } + + private AddressAccessInformation(boolean canTrap, int disp) { + this.canTrap = canTrap; + this.scale = Scale.Times1; + this.disp = disp; + } + + private AddressAccessInformation(boolean canTrap, int disp, Scale scale) { + this.canTrap = canTrap; + this.scale = scale; + this.disp = disp; + } + } + + /** + * A label that is the target of a control flow instruction. + */ + public static final class XirLabel { + public static final String TrueSuccessor = "TrueSuccessor"; + public static final String FalseSuccessor = "FalseSuccessor"; + public final String name; + public final int index; + /** + * If {@code true} the label is to an instruction in the fast path sequence, otherwise to the slow path. + */ + public final boolean inline; + + private XirLabel(String name, int index, boolean inline) { + this.name = name; + this.index = index; + this.inline = inline; + } + + @Override + public String toString() { + return name; + } + } + + /** + * Tagging interface that indicates that an {@link XirOperand} is a constant. + */ + public interface XirConstantOperand { + int getIndex(); + } + + public static final XirOperand VOID = null; + + /** + * Operands for {@link XirInstruction instructions}. + * There are three basic variants, {@link XirConstant constant}, {@link XirParameter parameter} and {@link XirTemp}. + */ + public abstract static class XirOperand { + + public final Kind kind; + + /** + * Unique id in range {@code 0} to {@link #variableCount variableCount - 1}. + */ + public final int index; + + /** + * Value whose {@link #toString()} method provides a name for this operand. + */ + public final Object name; + + public XirOperand(XirAssembler asm, Object name, Kind kind) { + this.kind = kind; + this.name = name; + this.index = asm.variableCount++; + } + + @Override + public String toString() { + return String.valueOf(name); + } + + public String detailedToString() { + + StringBuffer sb = new StringBuffer(); + + sb.append(name); + sb.append('$'); + sb.append(kind.typeChar); + return sb.toString(); + } + } + + /** + * Parameters to {@link XirTemplate templates}. + */ + public static class XirParameter extends XirOperand { + /** + * Unique id in range {@code 0} to {@code parameters.Size() - 1}. + */ + public final int parameterIndex; + + public final boolean canBeConstant; + + XirParameter(XirAssembler asm, String name, Kind kind, boolean canBeConstant) { + super(asm, name, kind); + this.parameterIndex = asm.parameters.size(); + this.canBeConstant = canBeConstant; + asm.parameters.add(this); + } + + } + + public static class XirConstantParameter extends XirParameter implements XirConstantOperand { + XirConstantParameter(XirAssembler asm, String name, Kind kind) { + super(asm, name, kind, true); + } + + public int getIndex() { + return index; + } + } + + public static class XirVariableParameter extends XirParameter { + XirVariableParameter(XirAssembler asm, String name, Kind kind, boolean canBeConstant) { + super(asm, name, kind, canBeConstant); + } + } + + public static class XirConstant extends XirOperand implements XirConstantOperand { + public final Constant value; + + XirConstant(XirAssembler asm, Constant value) { + super(asm, value, value.kind); + this.value = value; + } + + public int getIndex() { + return index; + } + } + + public static class XirTemp extends XirOperand { + public final boolean reserve; + + XirTemp(XirAssembler asm, String name, Kind kind, boolean reserve) { + super(asm, name, kind); + this.reserve = reserve; + } + } + + public static class XirRegister extends XirTemp { + public final Value register; + + XirRegister(XirAssembler asm, String name, RegisterValue register, boolean reserve) { + super(asm, name, register.kind, reserve); + this.register = register; + } + } + + /** + * Start a new assembly with no initial {@link #resultOperand result operand}. + */ + public void restart() { + reset(); + resultOperand = null; + } + + /** + * Start a new assembly with a {@link #resultOperand result operand} of type {@code kind}. + * @param kind the result kind + * @return an {@code XirOperand} for the result operand + */ + public XirOperand restart(Kind kind) { + reset(); + resultOperand = new XirTemp(this, "result", kind, true); + allocateResultOperand = true; + return resultOperand; + } + + /** + * Reset the state of the class to the initial conditions to facilitate a new assembly. + */ + private void reset() { + assert finished : "must be finished before!"; + variableCount = 0; + allocateResultOperand = false; + finished = false; + instructions.clear(); + labels.clear(); + parameters.clear(); + temps.clear(); + constants.clear(); + marks.clear(); + outgoingStackSize = 0; + } + + /** + * Represents an XIR instruction, characterized by an {@link XirOp operation}, a {@link Kind kind}, an optional {@link XirOperand result}, a variable number of {@link XirOperand arguments}, + * and some optional instruction-specific state. The {@link #x}, {@link #y} and {@link #z} methods are convenient ways to access the first, second and third + * arguments, respectively. Only {@link XirOp#CallRuntime} instructions can have more than three arguments. + * + */ + public static final class XirInstruction { + /** + * The {@link Kind kind} of values the instruction operates on. + */ + public final Kind kind; + /** + * The {@link XirOp operation}. + */ + public final XirOp op; + /** + * The result, if any. + */ + public final XirOperand result; + /** + * The arguments. + */ + public final XirOperand[] arguments; + /** + * Arbitrary additional data associated with the instruction. + */ + public final Object extra; + + public XirInstruction(Kind kind, XirOp op, XirOperand result, XirOperand... arguments) { + this(kind, null, op, result, arguments); + } + + public XirInstruction(Kind kind, Object extra, XirOp op, XirOperand result, XirOperand... arguments) { + this.extra = extra; + this.kind = kind; + this.op = op; + this.result = result; + this.arguments = arguments; + } + + public XirOperand x() { + assert arguments.length > 0 : "no x operand for this instruction"; + return arguments[0]; + } + + public XirOperand y() { + assert arguments.length > 1 : "no y operand for this instruction"; + return arguments[1]; + } + + public XirOperand z() { + assert arguments.length > 2 : "no z operand for this instruction"; + return arguments[2]; + } + + @Override + public String toString() { + StringBuffer sb = new StringBuffer(); + + if (result != null) { + sb.append(result.toString()); + sb.append(" = "); + } + + sb.append(op.name()); + + if (kind != Kind.Void) { + sb.append('$'); + sb.append(kind.typeChar); + } + + if (arguments != null && arguments.length > 0) { + sb.append("("); + + for (int i = 0; i < arguments.length; i++) { + if (i != 0) { + sb.append(", "); + } + sb.append(arguments[i]); + } + + sb.append(")"); + } + + if (extra != null) { + sb.append(" "); + sb.append(extra); + } + + return sb.toString(); + } + } + + /** + * These marks let the {@link XirGenerator} mark positions in the generated native code and bring them in relationship with on another. + * This is necessary for code patching, etc. + */ + public static class XirMark { + public final XirMark[] references; + public final Object id; + + // special mark used to refer to the actual call site of an invoke + public static final XirMark CALLSITE = new XirMark(null); + + public XirMark(Object id, XirMark... references) { + this.id = id; + this.references = references; + } + } + + /** + * The set of opcodes for XIR instructions. + * {@link XirInstruction} defines {@code x}, {@code y} and {@code z} as the first, second and third arguments, respectively. + * We use these mnemonics, plus {@code args} for the complete set of arguments, {@code r} for the result, and {@code extra} + * for the instruction-specific extra data, in the opcode specifications. Note that the opcodes that operate on values do not directly + * specify the size (kind) of the data operated on; this is is encoded in {@link XirInstruction#kind}. + * Note: If the instruction kind differs from the argument/result kinds, the behavior is undefined. + * + */ + public enum XirOp { + /** + * Move {@code x} to {@code r}. + */ + Mov, + /** + * Add {@code y} to {@code x} and put the result in {@code r}. + */ + Add, + /** + * Subtract {@code y} from {@code x} and put the result in {@code r}. + */ + Sub, + /** + * Divide {@code y} by {@code x} and put the result in {@code r}. + */ + Div, + /** + * Multiply {@code y} by {@code x} and put the result in {@code r}. + */ + Mul, + /** + * {@code y} modulus {@code x} and put the result in {@code r}. + */ + Mod, + /** + * Shift {@code y} left by {@code x} and put the result in {@code r}. + */ + Shl, + /** + * Arithmetic shift {@code y} right by {@code x} and put the result in {@code r}. + */ + Sar, + /** + * Shift {@code y} right by {@code x} and put the result in {@code r}. + */ + Shr, + /** + * And {@code y} by {@code x} and put the result in {@code r}. + */ + And, + /** + * Or {@code y} by {@code x} and put the result in {@code r}. + */ + Or, + /** + * Exclusive Or {@code y} by {@code x} and put the result in {@code r}. + */ + Xor, + /** + * Null check on {@code x}. + */ + NullCheck, + /** + * Load value at address {@code x} and put the result in {@code r}. + */ + PointerLoad, + /** + * Store {@code y} at address {@code x}. + */ + PointerStore, + /** + * Load value at an effective address defined by base {@code x} and either a scaled index {@code y} plus displacement + * or an offset {@code y} and put the result in {@code r}. + */ + PointerLoadDisp, + /** + * Load an effective address defined by base {@code x} and either a scaled index {@code y} plus displacement + * or an offset {@code y} and put the result in {@code r}. + */ + LoadEffectiveAddress, + /** + * Store {@code z} at address defined by base {@code x} and index {@code y}. + */ + PointerStoreDisp, + /** + * Repeat move from {@code x} to {@code y} using {@code z} words. + */ + RepeatMoveWords, + /** + * Repeat move from {@code x} to {@code y} using {@code z} words. + */ + RepeatMoveBytes, + /** + * Compare value at at address {@code x} with value in {@code y} and store value {@code z} at address {@code x} + * if it was equal to {@code y}. + */ + PointerCAS, + /** + * Call the {@link JavaMethod} defined by {@code extra} with {@code args} and put the result in {@code r}. + */ + CallRuntime, + /** + * Transfer control to the instruction at the {@link XirLabel label} identified by {@code extra}. + */ + Jmp, + /** + * If {@code x == y}, transfer control to the instruction at the {@link XirLabel label} identified by {@code extra}. + */ + Jeq, + /** + * If {@code x != y}, transfer control to the instruction at the {@link XirLabel label} identified by {@code extra}. + */ + Jneq, + /** + * If {@code x > y}, transfer control to the instruction at the {@link XirLabel label} identified by {@code extra}. + */ + Jgt, + /** + * If {@code x >= y}, transfer control to the instruction at the {@link XirLabel label} identified by {@code extra}. + */ + Jgteq, + /** + * If {@code x unsigned >= y}, transfer control to the instruction at the {@link XirLabel label} identified by {@code extra}. + */ + Jugteq, + /** + * If {@code x < y}, transfer control to the instruction at the {@link XirLabel label} identified by {@code extra}. + */ + Jlt, + /** + * If {@code x <= y}, transfer control to the instruction at the {@link XirLabel label} identified by {@code extra}. + */ + Jlteq, + /** + * Decreases the input by one and jumps to the target if the input is not 0. + */ + DecAndJumpNotZero, + /** + * If bit designated by {@code z} at effective address defined by base {@code x} and offset {@code y} + * is set transfer control to the instruction at the {@link XirLabel label} identified by {@code extra}. + */ + Jbset, + /** + * Bind the {@link XirLabel label} identified by {@code extra} to the current instruction and update any references to it. + * A label may be bound more than once to the same location. + */ + Bind, + /** + * Record a safepoint. + */ + Safepoint, + /** + * Pushes a value onto the stack. + */ + Push, + /** + * Pops a value from the stack. + */ + Pop, + /** + * Marks a position in the generated native code. + */ + Mark, + /** + * Load instruction pointer of the next instruction in a destination register. + */ + Here, + /** + * Inserts nop instructions, with the given size in bytes. + */ + Nop, + /** + * This instruction should never be reached, this is useful for debugging purposes. + */ + ShouldNotReachHere + } + + public/*private*/ void append(XirInstruction xirInstruction) { + assert !finished : "no instructions can be added to finished template"; + instructions.add(xirInstruction); + } + + public XirLabel createInlineLabel(String name) { + final XirLabel result = new XirLabel(name, this.labels.size(), true); + labels.add(result); + return result; + } + + public XirLabel createOutOfLineLabel(String name) { + final XirLabel result = new XirLabel(name, this.labels.size(), false); + labels.add(result); + return result; + } + + public void mov(XirOperand result, XirOperand a) { + append(new XirInstruction(result.kind, Mov, result, a)); + } + + public void add(XirOperand result, XirOperand a, XirOperand b) { + append(new XirInstruction(result.kind, Add, result, a, b)); + } + + public void sub(XirOperand result, XirOperand a, XirOperand b) { + append(new XirInstruction(result.kind, Sub, result, a, b)); + } + + public void div(XirOperand result, XirOperand a, XirOperand b) { + append(new XirInstruction(result.kind, Div, result, a, b)); + } + + public void mul(XirOperand result, XirOperand a, XirOperand b) { + append(new XirInstruction(result.kind, Mul, result, a, b)); + } + + public void mod(XirOperand result, XirOperand a, XirOperand b) { + append(new XirInstruction(result.kind, Mod, result, a, b)); + } + + public void shl(XirOperand result, XirOperand a, XirOperand b) { + append(new XirInstruction(result.kind, Shl, result, a, b)); + } + + public void shr(XirOperand result, XirOperand a, XirOperand b) { + append(new XirInstruction(result.kind, Shr, result, a, b)); + } + + public void and(XirOperand result, XirOperand a, XirOperand b) { + append(new XirInstruction(result.kind, And, result, a, b)); + } + + public void or(XirOperand result, XirOperand a, XirOperand b) { + append(new XirInstruction(result.kind, Or, result, a, b)); + } + + public void xor(XirOperand result, XirOperand a, XirOperand b) { + append(new XirInstruction(result.kind, Xor, result, a, b)); + } + + public void nullCheck(XirOperand pointer) { + append(new XirInstruction(Kind.Object, NullCheck, VOID, pointer)); + } + + public void pload(Kind kind, XirOperand result, XirOperand pointer, boolean canTrap) { + append(new XirInstruction(kind, canTrap, PointerLoad, result, pointer)); + } + + public void pstore(Kind kind, XirOperand pointer, XirOperand value, boolean canTrap) { + append(new XirInstruction(kind, canTrap, PointerStore, null, pointer, value)); + } + + public void pload(Kind kind, XirOperand result, XirOperand pointer, XirOperand offset, boolean canTrap) { + append(new XirInstruction(kind, new AddressAccessInformation(canTrap), PointerLoadDisp, result, pointer, offset)); + } + + public void pstore(Kind kind, XirOperand pointer, XirOperand offset, XirOperand value, boolean canTrap) { + append(new XirInstruction(kind, new AddressAccessInformation(canTrap), PointerStoreDisp, VOID, pointer, offset, value)); + } + + public void pload(Kind kind, XirOperand result, XirOperand pointer, XirOperand index, int disp, Scale scale, boolean canTrap) { + append(new XirInstruction(kind, new AddressAccessInformation(canTrap, disp, scale), PointerLoadDisp, result, pointer, index)); + } + + public void lea(XirOperand result, XirOperand pointer, XirOperand index, int disp, Scale scale) { + append(new XirInstruction(target.wordKind, new AddressAccessInformation(false, disp, scale), LoadEffectiveAddress, result, pointer, index)); + } + + public void repmov(XirOperand src, XirOperand dest, XirOperand length) { + append(new XirInstruction(target.wordKind, null, RepeatMoveWords, null, src, dest, length)); + } + + public void here(XirOperand dst) { + append(new XirInstruction(target.wordKind, null, Here, dst)); + } + + public void repmovb(XirOperand src, XirOperand dest, XirOperand length) { + append(new XirInstruction(target.wordKind, null, RepeatMoveBytes, null, src, dest, length)); + } + + public void pstore(Kind kind, XirOperand pointer, XirOperand index, XirOperand value, int disp, Scale scale, boolean canTrap) { + append(new XirInstruction(kind, new AddressAccessInformation(canTrap, disp, scale), PointerStoreDisp, VOID, pointer, index, value)); + } + + public void pcas(Kind kind, XirOperand result, XirOperand pointer, XirOperand newValue, XirOperand oldValue) { + append(new XirInstruction(kind, null, PointerCAS, result, pointer, newValue, oldValue)); + } + + public void jmp(XirLabel l) { + append(new XirInstruction(Kind.Void, l, Jmp, null)); + } + + public void decAndJumpNotZero(XirLabel l, XirOperand val) { + append(new XirInstruction(Kind.Void, l, DecAndJumpNotZero, null, val)); + } + + public void jmpRuntime(Object rt) { + append(new XirInstruction(Kind.Void, rt, Jmp, null)); + } + + public void jeq(XirLabel l, XirOperand a, XirOperand b) { + jcc(Jeq, l, a, b); + } + + private void jcc(XirOp op, XirLabel l, XirOperand a, XirOperand b) { + append(new XirInstruction(Kind.Void, l, op, null, a, b)); + } + + public void jneq(XirLabel l, XirOperand a, XirOperand b) { + jcc(Jneq, l, a, b); + } + + public void jgt(XirLabel l, XirOperand a, XirOperand b) { + jcc(Jgt, l, a, b); + } + + public void jgteq(XirLabel l, XirOperand a, XirOperand b) { + jcc(Jgteq, l, a, b); + } + + public void jugteq(XirLabel l, XirOperand a, XirOperand b) { + jcc(Jugteq, l, a, b); + } + + public void jlt(XirLabel l, XirOperand a, XirOperand b) { + jcc(Jlt, l, a, b); + } + + public void jlteq(XirLabel l, XirOperand a, XirOperand b) { + jcc(Jlteq, l, a, b); + } + + public void jbset(XirLabel l, XirOperand a, XirOperand b, XirOperand c) { + append(new XirInstruction(Kind.Void, l, Jbset, null, a, b, c)); + } + + public void bindInline(XirLabel l) { + assert l.inline; + append(new XirInstruction(Kind.Void, l, Bind, null)); + } + + public void bindOutOfLine(XirLabel l) { + assert !l.inline; + append(new XirInstruction(Kind.Void, l, Bind, null)); + } + + public void safepoint() { + append(new XirInstruction(Kind.Void, null, Safepoint, null)); + } + + public void push(XirOperand value) { + append(new XirInstruction(Kind.Void, Push, VOID, value)); + } + + public void pop(XirOperand result) { + append(new XirInstruction(result.kind, Pop, result)); + } + + public XirMark mark(Object id, XirMark... references) { + XirMark mark = new XirMark(id, references); + marks.add(mark); + append(new XirInstruction(Kind.Void, mark, Mark, null)); + return mark; + } + + public void nop(int size) { + append(new XirInstruction(Kind.Void, size, Nop, null)); + } + + public void shouldNotReachHere() { + append(new XirInstruction(Kind.Void, null, ShouldNotReachHere, null)); + } + + public void shouldNotReachHere(String message) { + append(new XirInstruction(Kind.Void, message, ShouldNotReachHere, null)); + } + + public void callRuntime(Object rt, XirOperand result, XirOperand... args) { + callRuntime(rt, result, false, args); + } + + public void callRuntime(Object rt, XirOperand result, boolean useInfoAfter, XirOperand... args) { + Kind resultKind = result == null ? Kind.Void : result.kind; + append(new XirInstruction(resultKind, new RuntimeCallInformation(rt, useInfoAfter), CallRuntime, result, args)); + } + + /** + * Terminates the assembly, checking invariants, in particular that {@link #resultOperand} is set, and setting {@link #finished} to {@code true}. + */ + private void end() { + assert !finished : "template may only be finished once!"; + assert resultOperand != null : "result operand should be set"; + finished = true; + } + + /** + * Creates an {@link XirVariableParameter variable input parameter} of given name and {@link Kind kind}. + * @param name a name for the parameter + * @param kind the parameter kind + * @return the {@link XirVariableParameter} + */ + public XirVariableParameter createInputParameter(String name, Kind kind, boolean canBeConstant) { + assert !finished; + return new XirVariableParameter(this, name, kind, canBeConstant); + } + + public XirVariableParameter createInputParameter(String name, Kind kind) { + return createInputParameter(name, kind, false); + } + + /** + * Creates an {@link XirConstantParameter constant input parameter} of given name and {@link Kind kind}. + * @param name a name for the parameter + * @param kind the parameter kind + * @return the {@link XirConstantParameter} + */ + public XirConstantParameter createConstantInputParameter(String name, Kind kind) { + assert !finished; + return new XirConstantParameter(this, name, kind); + } + + public XirConstant createConstant(Constant constant) { + assert !finished; + XirConstant temp = new XirConstant(this, constant); + constants.add(temp); + return temp; + } + + public XirOperand createTemp(String name, Kind kind) { + assert !finished; + XirTemp temp = new XirTemp(this, name, kind, true); + temps.add(temp); + return temp; + } + + public XirOperand createRegister(String name, Kind kind, Register register) { + return createRegister(name, kind, register, false); + } + + public XirOperand createRegisterTemp(String name, Kind kind, Register register) { + return createRegister(name, kind, register, true); + } + + private XirOperand createRegister(String name, Kind kind, Register register, boolean reserve) { + assert !finished; + XirRegister fixed = new XirRegister(this, name, register.asValue(kind), reserve); + temps.add(fixed); + return fixed; + } + + public XirParameter getParameter(String name) { + for (XirParameter param : parameters) { + if (param.name.toString().equals(name)) { + return param; + } + } + throw new IllegalArgumentException("no parameter: " + name); + } + + public XirTemp getTemp(String name) { + for (XirTemp temp : temps) { + if (temp.name.toString().equals(name)) { + return temp; + } + } + throw new IllegalArgumentException("no temp: " + name); + } + + public XirConstant i(int v) { + return createConstant(Constant.forInt(v)); + } + + public XirConstant l(long v) { + return createConstant(Constant.forLong(v)); + } + + public XirConstant b(boolean v) { + return createConstant(Constant.forBoolean(v)); + } + + public XirConstant o(Object obj) { + return createConstant(Constant.forObject(obj)); + } + + public void reserveOutgoingStack(int size) { + outgoingStackSize = Math.max(outgoingStackSize, size); + } + + /** + * Finishes the assembly of a non-stub template, providing the {@link #resultOperand} and constructs the {@link XirTemplate}. + * @param result the {@link XirOperand} to be set as the {@link #resultOperand} + * @param name the name of the template + * @return the generated template + */ + public XirTemplate finishTemplate(XirOperand result, String name) { + assert this.resultOperand == null; + assert result != null; + this.resultOperand = result; + final XirTemplate template = buildTemplate(name, false); + end(); + return template; + } + + /** + * Finishes the assembly of a non-stub template and constructs the {@link XirTemplate}. + * @param name the name of the template + * @return the generated template + */ + public XirTemplate finishTemplate(String name) { + final XirTemplate template = buildTemplate(name, false); + end(); + return template; + } + + /** + * Finishes the assembly of a {@link XirTemplate.GlobalFlags#GLOBAL_STUB stub} and constructs the {@link XirTemplate}. + * @param name the name of the template + * @return the generated template + */ + public XirTemplate finishStub(String name) { + final XirTemplate template = buildTemplate(name, true); + end(); + return template; + } + + /** + * Builds the {@link XirTemplate} from the assembly state in this object. + * The actual assembly is dependent on the target architecture and implemented + * in a concrete subclass. + * @param name the name of the template + * @param isStub {@code true} if the template represents a {@link XirTemplate.GlobalFlags#GLOBAL_STUB stub} + * @return the generated template + */ + protected abstract XirTemplate buildTemplate(String name, boolean isStub); + + public abstract XirAssembler copy(); + +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.max.cri/src/com/oracle/max/cri/xir/XirGenerator.java Mon Jul 09 14:22:22 2012 +0200 @@ -0,0 +1,76 @@ +/* + * Copyright (c) 2009, 2011, 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. + */ +package com.oracle.max.cri.xir; + +import com.oracle.graal.api.meta.*; +import com.oracle.graal.api.meta.JavaType.*; + +/** + * Represents the interface through which the compiler requests the XIR for a given bytecode from the runtime system. + */ +public interface XirGenerator { + + XirSnippet genInvokeInterface(XirSite site, XirArgument receiver, JavaMethod method); + + XirSnippet genInvokeVirtual(XirSite site, XirArgument receiver, JavaMethod method, boolean megamorph); + + XirSnippet genInvokeSpecial(XirSite site, XirArgument receiver, JavaMethod method); + + XirSnippet genInvokeStatic(XirSite site, JavaMethod method); + + XirSnippet genMonitorEnter(XirSite site, XirArgument receiver, XirArgument lockAddress); + + XirSnippet genMonitorExit(XirSite site, XirArgument receiver, XirArgument lockAddress); + + XirSnippet genNewInstance(XirSite site, JavaType type); + + XirSnippet genNewArray(XirSite site, XirArgument length, Kind elementKind, JavaType componentType, JavaType arrayType); + + XirSnippet genNewMultiArray(XirSite site, XirArgument[] lengths, JavaType type); + + XirSnippet genCheckCast(XirSite site, XirArgument receiver, XirArgument hub, ResolvedJavaType type, JavaTypeProfile profile); + + XirSnippet genInstanceOf(XirSite site, XirArgument receiver, XirArgument hub, ResolvedJavaType type, JavaTypeProfile profile); + + XirSnippet genMaterializeInstanceOf(XirSite site, XirArgument receiver, XirArgument hub, XirArgument trueValue, XirArgument falseValue, ResolvedJavaType type, JavaTypeProfile profile); + + /** + * Generates code that checks that the {@linkplain Representation#ObjectHub hub} of + * an object is identical to a given hub constant. In pseudo code: + * <pre> + * if (object.getHub() != hub) { + * jump(falseSuccessor) + * } + * </pre> + * This snippet should only be used when the object is guaranteed not to be null. + */ + XirSnippet genTypeBranch(XirSite site, XirArgument thisHub, XirArgument otherHub, JavaType type); + + /** + * Initializes the XIR generator for the given XIR assembler. + * + * @param asm the XIR assembler + */ + void initialize(XirAssembler asm); + +}
--- a/graal/com.oracle.max.cri/src/com/oracle/max/cri/xir/XirSite.java Mon Jul 09 14:15:55 2012 +0200 +++ b/graal/com.oracle.max.cri/src/com/oracle/max/cri/xir/XirSite.java Mon Jul 09 14:22:22 2012 +0200 @@ -25,7 +25,7 @@ import com.oracle.graal.api.code.*; /** - * Encapsulates the notion of a site where XIR can be supplied. It is supplied to the {@link RiXirGenerator} by the + * Encapsulates the notion of a site where XIR can be supplied. It is supplied to the {@link XirGenerator} by the * compiler for each place where XIR can be generated. This interface allows a number of queries, including the * bytecode-level location and optimization hints computed by the compiler. */
--- a/graal/com.oracle.max.cri/src/com/oracle/max/cri/xir/XirSnippet.java Mon Jul 09 14:15:55 2012 +0200 +++ b/graal/com.oracle.max.cri/src/com/oracle/max/cri/xir/XirSnippet.java Mon Jul 09 14:22:22 2012 +0200 @@ -26,7 +26,7 @@ import com.oracle.graal.api.code.CompilationResult.*; import com.oracle.graal.api.meta.*; -import com.oracle.max.cri.xir.CiXirAssembler.*; +import com.oracle.max.cri.xir.XirAssembler.*; /** * Represents a {@link XirTemplate template of XIR} along with the {@link XirArgument arguments} to be passed to the
--- a/graal/com.oracle.max.cri/src/com/oracle/max/cri/xir/XirTemplate.java Mon Jul 09 14:15:55 2012 +0200 +++ b/graal/com.oracle.max.cri/src/com/oracle/max/cri/xir/XirTemplate.java Mon Jul 09 14:22:22 2012 +0200 @@ -25,7 +25,7 @@ import java.io.*; import java.util.*; -import com.oracle.max.cri.xir.CiXirAssembler.*; +import com.oracle.max.cri.xir.XirAssembler.*; /** * Represents a completed template of XIR code that has been first assembled by @@ -71,12 +71,12 @@ /** * The sequence of instructions for the fast (inline) path. */ - public final CiXirAssembler.XirInstruction[] fastPath; + public final XirAssembler.XirInstruction[] fastPath; /** * The sequence of instructions for the slow (out of line) path. */ - public final CiXirAssembler.XirInstruction[] slowPath; + public final XirAssembler.XirInstruction[] slowPath; /** * Labels used in control transfers. @@ -130,8 +130,8 @@ int variableCount, boolean allocateResultOperand, XirOperand resultOperand, - CiXirAssembler.XirInstruction[] fastPath, - CiXirAssembler.XirInstruction[] slowPath, + XirAssembler.XirInstruction[] fastPath, + XirAssembler.XirInstruction[] slowPath, XirLabel[] labels, XirParameter[] parameters, XirTemp[] temps,
--- a/graal/com.oracle.max.cri/src/com/oracle/max/cri/xir/package-info.java Mon Jul 09 14:15:55 2012 +0200 +++ b/graal/com.oracle.max.cri/src/com/oracle/max/cri/xir/package-info.java Mon Jul 09 14:22:22 2012 +0200 @@ -24,14 +24,14 @@ * XIR defines a domain specific instruction set for expressing the lowering of bytecode operations. The details of the * lowering operations are entirely encapsulated in the runtime and are provided to the compiler on request using * {@link com.oracle.max.cri.xir.XirSnippet XIR snippets}. A snippet is a combination of a {@link com.oracle.max.cri.xir.XirTemplate - * template}, which is a sequence of {@link com.oracle.max.cri.xir.CiXirAssembler.XirInstruction XIR instructions} that has - * unbound {@link com.oracle.max.cri.xir.CiXirAssembler.XirParameter parameters}, and site-specific + * template}, which is a sequence of {@link com.oracle.max.cri.xir.XirAssembler.XirInstruction XIR instructions} that has + * unbound {@link com.oracle.max.cri.xir.XirAssembler.XirParameter parameters}, and site-specific * {@link com.oracle.max.cri.xir.XirArgument arguments} that are bound to the parameters. * <p> * The runtime is responsible for creating the {@link com.oracle.max.cri.xir.XirTemplate templates} and provides these to the * compiler as part of the initialization process. * <p> * The XIR instruction set has no textual representation, and therefore no parser. An assembly is represented by an - * instance of {@link com.oracle.max.cri.xir.CiXirAssembler}, which provides methods to create instructions and operands. + * instance of {@link com.oracle.max.cri.xir.XirAssembler}, which provides methods to create instructions and operands. */ package com.oracle.max.cri.xir;
--- a/graal/com.oracle.max.criutils/src/com/oracle/max/criutils/UnsignedMath.java Mon Jul 09 14:15:55 2012 +0200 +++ b/graal/com.oracle.max.criutils/src/com/oracle/max/criutils/UnsignedMath.java Mon Jul 09 14:22:22 2012 +0200 @@ -22,6 +22,8 @@ */ package com.oracle.max.criutils; +//JaCoCo Exclude + /** * Utilities for unsigned comparisons. * All methods have correct, but slow, standard Java implementations so that
--- a/mx/commands.py Mon Jul 09 14:15:55 2012 +0200 +++ b/mx/commands.py Mon Jul 09 14:22:22 2012 +0200 @@ -587,7 +587,9 @@ # Exclude all compiler tests and snippets excludes = ['com.oracle.graal.compiler.tests.*'] for p in mx.projects(): - _find_classes_with_annotations(excludes, p, None, ['@Snippet', '@ClassSubstitution'], includeInnerClasses=True) + excludes += _find_classes_with_annotations(p, None, ['@Snippet', '@ClassSubstitution'], includeInnerClasses=True) + excludes += p.find_classes_with_matching_source_line(None, lambda line: 'JaCoCo Exclude' in line, includeInnerClasses=True) + agentOptions = { 'append' : 'true' if _jacoco == 'append' else 'false', 'bootclasspath' : 'true', @@ -598,47 +600,15 @@ exe = join(jdk, 'bin', mx.exe_suffix('java')) return mx.run([exe, '-' + vm] + args, nonZeroIsFatal=nonZeroIsFatal, out=out, err=err, cwd=cwd, timeout=timeout) -def _find_classes_with_annotations(classes, p, pkgRoot, annotations, includeInnerClasses=False): +def _find_classes_with_annotations(p, pkgRoot, annotations, includeInnerClasses=False): """ Scan the sources of project 'p' for Java source files containing a line starting with 'annotation' - (ignoring preceding whitespace) and add the fully qualified class name - to 'classes' for each Java source file matched. + (ignoring preceding whitespace) and return the fully qualified class name for each Java + source file matched in a list. """ - for a in annotations: - assert a.startswith('@') - pkgDecl = re.compile(r"^package\s+([a-zA-Z_][\w\.]*)\s*;$") - for srcDir in p.source_dirs(): - outputDir = p.output_dir() - for root, _, files in os.walk(srcDir): - for name in files: - if name.endswith('.java') and name != 'package-info.java': - annotationFound = False - with open(join(root, name)) as f: - pkg = None - for line in f: - if line.startswith("package "): - match = pkgDecl.match(line) - if match: - pkg = match.group(1) - else: - stripped = line.strip() - for a in annotations: - if stripped == a or stripped.startswith(a + '('): - annotationFound = True - break - if annotationFound: - break - if annotationFound: - basename = name[:-len('.java')] - assert pkg is not None - if pkgRoot is None or pkg.startswith(pkgRoot): - pkgOutputDir = join(outputDir, pkg.replace('.', os.path.sep)) - for e in os.listdir(pkgOutputDir): - if includeInnerClasses: - if e.endswith('.class') and (e.startswith(basename) or e.startswith(basename + '$')): - classes.append(pkg + '.' + e[:-len('.class')]) - elif e == basename + '.class': - classes.append(pkg + '.' + basename) + + matches = lambda line : len([a for a in annotations if line == a or line.startswith(a + '(')]) != 0 + return p.find_classes_with_matching_source_line(pkgRoot, matches, includeInnerClasses) def _run_tests(args, harnessName, harness): pos = [a for a in args if a[0] != '-' and a[0] != '@' ] @@ -653,8 +623,7 @@ for p in mx.projects(): if getattr(p, 'testHarness', None) == harnessName: - classes = [] - _find_classes_with_annotations(classes, p, None, ['@Test']) + classes = _find_classes_with_annotations(p, None, ['@Test']) if len(pos) != 0: classes = [c for c in classes if containsAny(c, pos)] @@ -1000,142 +969,18 @@ mx.abort('jacocoreport takes only one argument : an output directory') mx.run_java(['-jar', jacocoreport.get_path(True), '-in', 'jacoco.exec', '-g', join(_graal_home, 'graal'), out]) -def _fix_overview_summary(path, topLink): - """ - Processes an "overview-summary.html" generated by javadoc to put the complete - summary text above the Packages table. - """ - - # This uses scraping and so will break if the relevant content produced by javadoc changes in any way! - with open(path) as fp: - content = fp.read() - - class Chunk: - def __init__(self, content, ldelim, rdelim): - lindex = content.find(ldelim) - rindex = content.find(rdelim) - self.ldelim = ldelim - self.rdelim = rdelim - if lindex != -1 and rindex != -1 and rindex > lindex: - self.text = content[lindex + len(ldelim):rindex] - else: - self.text = None - - def replace(self, content, repl): - lindex = content.find(self.ldelim) - rindex = content.find(self.rdelim) - old = content[lindex:rindex + len(self.rdelim)] - return content.replace(old, repl) - - chunk1 = Chunk(content, """<div class="header"> -<div class="subTitle"> -<div class="block">""", """</div> -</div> -<p>See: <a href="#overview_description">Description</a></p> -</div>""") - - chunk2 = Chunk(content, """<div class="footer"><a name="overview_description"> -<!-- --> -</a> -<div class="subTitle"> -<div class="block">""", """</div> -</div> -</div> -<!-- ======= START OF BOTTOM NAVBAR ====== -->""") - - assert chunk1.text, 'Could not find header section in ' + path - assert chunk2.text, 'Could not find footer section in ' + path - - content = chunk1.replace(content, '<div class="header"><div class="subTitle"><div class="block">' + topLink + chunk2.text +'</div></div></div>') - content = chunk2.replace(content, '') - - with open(path, 'w') as fp: - fp.write(content) - def site(args): """creates a website containing javadoc and the project dependency graph""" - parser = ArgumentParser(prog='site') - parser.add_argument('-d', '--base', action='store', help='directory for generated site', required=True, metavar='<dir>') - - args = parser.parse_args(args) - - args.base = os.path.abspath(args.base) - tmpbase = tempfile.mkdtemp(prefix=basename(args.base) + '.', dir=dirname(args.base)) - unified = join(tmpbase, 'all') - - try: - # Create javadoc for each project - mx.javadoc(['--base', tmpbase]) - - # Create unified javadoc for all projects - mx.javadoc(['--base', tmpbase, - '--unified', - '--arg', '@-windowtitle', '--arg', '@Graal OpenJDK Project Documentation', - '--arg', '@-doctitle', '--arg', '@Graal OpenJDK Project Documentation', - '--arg', '@-overview', '--arg', '@' + join(_graal_home, 'graal', 'overview.html')]) - os.rename(join(tmpbase, 'javadoc'), unified) - - # Generate dependency graph with Graphviz - _, tmp = tempfile.mkstemp() - try: - svg = join(tmpbase, 'all', 'modules.svg') - jpg = join(tmpbase, 'all', 'modules.jpg') - with open(tmp, 'w') as fp: - print >> fp, 'digraph projects {' - print >> fp, 'rankdir=BT;' - print >> fp, 'size = "13,13";' - print >> fp, 'node [shape=rect, fontcolor="blue"];' - #print >> fp, 'edge [color="green"];' - for p in mx.projects(): - print >> fp, '"' + p.name + '" [URL = "../' + p.name + '/javadoc/index.html", target = "_top"]' - for dep in p.canonical_deps(): - if mx.project(dep, False): - print >> fp, '"' + p.name + '" -> "' + dep + '"' - depths = dict() - for p in mx.projects(): - d = p.max_depth() - depths.setdefault(d, list()).append(p.name) - for d, names in depths.iteritems(): - print >> fp, '{ rank = same; "' + '"; "'.join(names) + '"; }' - print >> fp, '}' - - mx.run(['dot', '-Tsvg', '-o' + svg, '-Tjpg', '-o' + jpg, tmp]) - - finally: - os.remove(tmp) - - # Post-process generated SVG to remove title elements which most browsers - # render as redundant (and annoying) tooltips. - with open(svg, 'r') as fp: - content = fp.read() - content = re.sub('<title>.*</title>', '', content) - content = re.sub('xlink:title="[^"]*"', '', content) - with open(svg, 'w') as fp: - fp.write(content) - - # Post-process generated overview-summary.html files - top = join(tmpbase, 'all', 'overview-summary.html') - for root, _, files in os.walk(tmpbase): - for f in files: - if f == 'overview-summary.html': - path = join(root, f) - topLink = '' - if top != path: - link = os.path.relpath(join(tmpbase, 'all', 'index.html'), dirname(path)) - topLink = '<p><a href="' + link + '", target="_top"><b>[return to the overall Graal documentation]</b></a></p>' - _fix_overview_summary(path, topLink) - - - if exists(args.base): - shutil.rmtree(args.base) - shutil.move(tmpbase, args.base) - - print 'Created website - root is ' + join(args.base, 'all', 'index.html') - - finally: - if exists(tmpbase): - shutil.rmtree(tmpbase) + return mx.site(['--name', 'Graal', + '--jd', '@-tag', '--jd', '@test:X', + '--jd', '@-tag', '--jd', '@run:X', + '--jd', '@-tag', '--jd', '@bug:X', + '--jd', '@-tag', '--jd', '@summary:X', + '--jd', '@-tag', '--jd', '@vmoption:X', + '--overview', join(_graal_home, 'graal', 'overview.html'), + '--title', 'Graal OpenJDK Project Documentation', + '--dot-output-base', 'modules'] + args) def mx_init(): _vmbuild = 'product'
--- a/mxtool/mx.py Mon Jul 09 14:15:55 2012 +0200 +++ b/mxtool/mx.py Mon Jul 09 14:22:22 2012 +0200 @@ -261,6 +261,46 @@ if not self.native: cp.append(self.output_dir()) + def find_classes_with_matching_source_line(self, pkgRoot, function, includeInnerClasses=False): + """ + Scan the sources of this project for Java source files containing a line for which + 'function' returns true. The fully qualified class name of each existing class + corresponding to a matched source file is returned in a list. + """ + classes = [] + pkgDecl = re.compile(r"^package\s+([a-zA-Z_][\w\.]*)\s*;$") + for srcDir in self.source_dirs(): + outputDir = self.output_dir() + for root, _, files in os.walk(srcDir): + for name in files: + if name.endswith('.java') and name != 'package-info.java': + matchFound = False + with open(join(root, name)) as f: + pkg = None + for line in f: + if line.startswith("package "): + match = pkgDecl.match(line) + if match: + pkg = match.group(1) + if function(line.strip()): + matchFound = True + if pkg and matchFound: + break + + if matchFound: + basename = name[:-len('.java')] + assert pkg is not None + if pkgRoot is None or pkg.startswith(pkgRoot): + pkgOutputDir = join(outputDir, pkg.replace('.', os.path.sep)) + for e in os.listdir(pkgOutputDir): + if includeInnerClasses: + if e.endswith('.class') and (e.startswith(basename) or e.startswith(basename + '$')): + classes.append(pkg + '.' + e[:-len('.class')]) + elif e == basename + '.class': + classes.append(pkg + '.' + basename) + return classes + + class Library(Dependency): def __init__(self, suite, name, path, mustExist, urls): Dependency.__init__(self, suite, name) @@ -1115,6 +1155,7 @@ parser.add_argument('--no-java', action='store_false', dest='java', help='do not build Java projects') parser.add_argument('--no-native', action='store_false', dest='native', help='do not build native projects') parser.add_argument('--jdt', help='Eclipse installation or path to ecj.jar for using the Eclipse batch compiler (default: ' + defaultEcjPath + ')', default=defaultEcjPath, metavar='<path>') + parser.add_argument('--jdt-warning-as-error', action='store_true', help='convert all Eclipse batch compiler warnings to errors') if suppliedParser: parser.add_argument('remainder', nargs=REMAINDER, metavar='...') @@ -1245,6 +1286,7 @@ argfile.write('\n'.join(javafilelist)) argfile.close() + toBeDeleted = [argfileName] try: if jdtJar is None: log('Compiling Java sources for {0} with javac...'.format(p.name)) @@ -1265,11 +1307,22 @@ if not exists(jdtProperties): log('JDT properties file {0} not found'.format(jdtProperties)) else: - jdtArgs += ['-properties', jdtProperties] + # convert all warnings to errors + if args.jdt_warning_as_error: + jdtPropertiesTmp = jdtProperties + '.tmp' + with open(jdtProperties) as fp: + content = fp.read().replace('=warning', '=error') + with open(jdtPropertiesTmp, 'w') as fp: + fp.write(content) + toBeDeleted.append(jdtPropertiesTmp) + jdtArgs += ['-properties', jdtPropertiesTmp] + else: + jdtArgs += ['-properties', jdtProperties] jdtArgs.append('@' + argfile.name) run(jdtArgs) finally: - os.remove(argfileName) + for n in toBeDeleted: + os.remove(n) if suppliedParser: return args @@ -1953,6 +2006,7 @@ parser.add_argument('--arg', action='append', dest='extra_args', help='extra Javadoc arguments (e.g. --arg @-use)', metavar='@<arg>', default=[]) parser.add_argument('-m', '--memory', action='store', help='-Xmx value to pass to underlying JVM') parser.add_argument('--packages', action='store', help='comma separated packages to process (omit to process all packages)') + parser.add_argument('--exclude-packages', action='store', help='comma separated packages to exclude') args = parser.parse_args(args) @@ -1966,6 +2020,10 @@ if args.packages is not None: packages = [name for name in args.packages.split(',')] + exclude_packages = [] + if args.exclude_packages is not None: + exclude_packages = [name for name in args.exclude_packages.split(',')] + def outDir(p): if args.base is None: return join(p.dir, docDir) @@ -1999,7 +2057,8 @@ if len([name for name in files if name.endswith('.java')]) != 0: pkg = root[len(sourceDir) + 1:].replace(os.sep,'.') if len(packages) == 0 or pkg in packages: - pkgs.add(pkg) + if len(exclude_packages) == 0 or not pkg in exclude_packages: + pkgs.add(pkg) return pkgs extraArgs = [a.lstrip('@') for a in args.extra_args] @@ -2026,26 +2085,33 @@ cp = classpath(p.name, includeSelf=True) sp = os.pathsep.join(p.source_dirs()) overviewFile = join(p.dir, 'overview.html') - overview = [] - if exists(overviewFile): - overview = ['-overview', overviewFile] + delOverviewFile = False + if not exists(overviewFile): + with open(overviewFile, 'w') as fp: + print >> fp, '<html><body>Documentation for the <code>' + p.name + '</code> project.</body></html>' + delOverviewFile = True nowarnAPI = [] if not args.warnAPI: nowarnAPI.append('-XDignore.symbol.file') - log('Generating {2} for {0} in {1}'.format(p.name, out, docDir)) - run([java().javadoc, memory, - '-windowtitle', p.name + ' javadoc', - '-XDignore.symbol.file', - '-classpath', cp, - '-quiet', - '-d', out, - '-sourcepath', sp] + - links + - extraArgs + - overview + - nowarnAPI + - list(pkgs)) - log('Generated {2} for {0} in {1}'.format(p.name, out, docDir)) + try: + log('Generating {2} for {0} in {1}'.format(p.name, out, docDir)) + run([java().javadoc, memory, + '-windowtitle', p.name + ' javadoc', + '-XDignore.symbol.file', + '-classpath', cp, + '-quiet', + '-d', out, + '-overview', overviewFile, + '-sourcepath', sp] + + links + + extraArgs + + nowarnAPI + + list(pkgs)) + log('Generated {2} for {0} in {1}'.format(p.name, out, docDir)) + finally: + if delOverviewFile: + os.remove(overviewFile) + else: # The projects must be built to ensure javadoc can find class files for all referenced classes build(['--no-native']) @@ -2079,6 +2145,162 @@ list(pkgs)) log('Generated {2} for {0} in {1}'.format(', '.join(names), out, docDir)) +def site(args): + """creates a website containing javadoc and the project dependency graph""" + + parser = ArgumentParser(prog='site') + parser.add_argument('-d', '--base', action='store', help='directory for generated site', required=True, metavar='<dir>') + parser.add_argument('--name', action='store', help='name of overall documentation', required=True, metavar='<name>') + parser.add_argument('--overview', action='store', help='path to the overview content for overall documentation', required=True, metavar='<path>') + parser.add_argument('--projects', action='store', help='comma separated projects to process (omit to process all projects)') + parser.add_argument('--jd', action='append', help='extra Javadoc arguments (e.g. --jd @-use)', metavar='@<arg>', default=[]) + parser.add_argument('--exclude-packages', action='store', help='comma separated packages to exclude', metavar='<pkgs>') + parser.add_argument('--dot-output-base', action='store', help='base file name (relative to <dir>/all) for project dependency graph .svg and .jpg files generated by dot (omit to disable dot generation)', metavar='<path>') + parser.add_argument('--title', action='store', help='value used for -windowtitle and -doctitle javadoc args for overall documentation (default: "<name>")', metavar='<title>') + args = parser.parse_args(args) + + args.base = os.path.abspath(args.base) + tmpbase = tempfile.mkdtemp(prefix=basename(args.base) + '.', dir=dirname(args.base)) + unified = join(tmpbase, 'all') + + exclude_packages_arg = [] + if args.exclude_packages is not None: + exclude_packages_arg = ['--exclude-packages', args.exclude_packages] + + projects = sorted_deps() + projects_arg = [] + if args.projects is not None: + projects_arg = ['--projects', args.projects] + projects = [project(name) for name in args.projects.split(',')] + + extra_javadoc_args = [] + for a in args.jd: + extra_javadoc_args.append('--arg') + extra_javadoc_args.append('@' + a) + + try: + # Create javadoc for each project + javadoc(['--base', tmpbase] + exclude_packages_arg + projects_arg + extra_javadoc_args) + + # Create unified javadoc for all projects + title = args.title if args.title is not None else args.name + javadoc(['--base', tmpbase, + '--unified', + '--arg', '@-windowtitle', '--arg', '@' + title, + '--arg', '@-doctitle', '--arg', '@' + title, + '--arg', '@-overview', '--arg', '@' + args.overview] + exclude_packages_arg + projects_arg + extra_javadoc_args) + os.rename(join(tmpbase, 'javadoc'), unified) + + # Generate dependency graph with Graphviz + if args.dot_output_base is not None: + dot = join(tmpbase, 'all', str(args.dot_output_base) + '.dot') + svg = join(tmpbase, 'all', str(args.dot_output_base) + '.svg') + jpg = join(tmpbase, 'all', str(args.dot_output_base) + '.jpg') + with open(dot, 'w') as fp: + dim = len(projects) + print >> fp, 'digraph projects {' + print >> fp, 'rankdir=BT;' + print >> fp, 'size = "' + str(dim) + ',' + str(dim) + '";' + print >> fp, 'node [shape=rect, fontcolor="blue"];' + #print >> fp, 'edge [color="green"];' + for p in projects: + print >> fp, '"' + p.name + '" [URL = "../' + p.name + '/javadoc/index.html", target = "_top"]' + for dep in p.canonical_deps(): + if dep in [proj.name for proj in projects]: + print >> fp, '"' + p.name + '" -> "' + dep + '"' + depths = dict() + for p in projects: + d = p.max_depth() + depths.setdefault(d, list()).append(p.name) + print >> fp, '}' + + run(['dot', '-Tsvg', '-o' + svg, '-Tjpg', '-o' + jpg, dot]) + + # Post-process generated SVG to remove title elements which most browsers + # render as redundant (and annoying) tooltips. + with open(svg, 'r') as fp: + content = fp.read() + content = re.sub('<title>.*</title>', '', content) + content = re.sub('xlink:title="[^"]*"', '', content) + with open(svg, 'w') as fp: + fp.write(content) + + # Post-process generated overview-summary.html files + + def fix_overview_summary(path, topLink): + """ + Processes an "overview-summary.html" generated by javadoc to put the complete + summary text above the Packages table. + """ + + # This uses scraping and so will break if the relevant content produced by javadoc changes in any way! + with open(path) as fp: + content = fp.read() + + class Chunk: + def __init__(self, content, ldelim, rdelim): + lindex = content.find(ldelim) + rindex = content.find(rdelim) + self.ldelim = ldelim + self.rdelim = rdelim + if lindex != -1 and rindex != -1 and rindex > lindex: + self.text = content[lindex + len(ldelim):rindex] + else: + self.text = None + + def replace(self, content, repl): + lindex = content.find(self.ldelim) + rindex = content.find(self.rdelim) + old = content[lindex:rindex + len(self.rdelim)] + return content.replace(old, repl) + + chunk1 = Chunk(content, """<div class="header"> +<div class="subTitle"> +<div class="block">""", """</div> +</div> +<p>See: <a href="#overview_description">Description</a></p> +</div>""") + + chunk2 = Chunk(content, """<div class="footer"><a name="overview_description"> +<!-- --> +</a> +<div class="subTitle"> +<div class="block">""", """</div> +</div> +</div> +<!-- ======= START OF BOTTOM NAVBAR ====== -->""") + + assert chunk1.text, 'Could not find header section in ' + path + assert chunk2.text, 'Could not find footer section in ' + path + + content = chunk1.replace(content, '<div class="header"><div class="subTitle"><div class="block">' + topLink + chunk2.text +'</div></div></div>') + content = chunk2.replace(content, '') + + with open(path, 'w') as fp: + fp.write(content) + + top = join(tmpbase, 'all', 'overview-summary.html') + for root, _, files in os.walk(tmpbase): + for f in files: + if f == 'overview-summary.html': + path = join(root, f) + topLink = '' + if top != path: + link = os.path.relpath(join(tmpbase, 'all', 'index.html'), dirname(path)) + topLink = '<p><a href="' + link + '", target="_top"><b>[return to the overall ' + args.name + ' documentation]</b></a></p>' + fix_overview_summary(path, topLink) + + + if exists(args.base): + shutil.rmtree(args.base) + shutil.move(tmpbase, args.base) + + print 'Created website - root is ' + join(args.base, 'all', 'index.html') + + finally: + if exists(tmpbase): + shutil.rmtree(tmpbase) + def findclass(args): """find all classes matching a given substring""" @@ -2141,6 +2363,7 @@ 'projectgraph': [projectgraph, ''], 'javap': [javap, ''], 'javadoc': [javadoc, '[options]'], + 'site': [site, '[options]'], 'netbeansinit': [netbeansinit, ''], 'projects': [show_projects, ''], }
--- a/src/share/tools/IdealGraphVisualizer/Bytecodes/src/com/sun/hotspot/igv/bytecodes/BytecodeNode.java Mon Jul 09 14:15:55 2012 +0200 +++ b/src/share/tools/IdealGraphVisualizer/Bytecodes/src/com/sun/hotspot/igv/bytecodes/BytecodeNode.java Mon Jul 09 14:22:22 2012 +0200 @@ -49,7 +49,7 @@ public BytecodeNode(InputBytecode bytecode, InputGraph graph, String bciValue) { super(Children.LEAF); - this.setDisplayName(bytecode.getBci() + " " + bytecode.getName()); + String displayName = bytecode.getBci() + " " + bytecode.getName() + " " + bytecode.getOperands(); bciValue = bytecode.getBci() + " " + bciValue; bciValue = bciValue.trim(); @@ -62,8 +62,14 @@ for (InputNode n : nodeList) { nodes.add(n); } - this.setDisplayName(this.getDisplayName() + " (" + nodes.size() + " nodes)"); + displayName += " (" + nodes.size() + " nodes)"; } + + if (bytecode.getComment() != null) { + displayName += " // " + bytecode.getComment(); + } + + this.setDisplayName(displayName); } @Override
--- a/src/share/tools/IdealGraphVisualizer/Data/src/com/sun/hotspot/igv/data/InputBytecode.java Mon Jul 09 14:15:55 2012 +0200 +++ b/src/share/tools/IdealGraphVisualizer/Data/src/com/sun/hotspot/igv/data/InputBytecode.java Mon Jul 09 14:22:22 2012 +0200 @@ -31,11 +31,15 @@ private int bci; private String name; + private String operands; + private String comment; private InputMethod inlined; - public InputBytecode(int bci, String name) { + public InputBytecode(int bci, String name, String operands, String comment) { this.bci = bci; this.name = name; + this.operands = operands; + this.comment = comment; } public InputMethod getInlined() { @@ -53,4 +57,12 @@ public String getName() { return name; } + + public String getOperands() { + return operands; + } + + public String getComment() { + return comment; + } }
--- a/src/share/tools/IdealGraphVisualizer/Data/src/com/sun/hotspot/igv/data/InputMethod.java Mon Jul 09 14:15:55 2012 +0200 +++ b/src/share/tools/IdealGraphVisualizer/Data/src/com/sun/hotspot/igv/data/InputMethod.java Mon Jul 09 14:22:22 2012 +0200 @@ -26,6 +26,8 @@ import java.util.ArrayList; import java.util.Collections; import java.util.List; +import java.util.regex.Matcher; +import java.util.regex.Pattern; /** * @@ -109,31 +111,38 @@ } public void setBytecodes(String text) { - + Pattern instruction = Pattern.compile("\\s*(\\d+)\\s*:?\\s*(\\w+)\\s*(.*)(?://(.*))?"); String[] strings = text.split("\n"); - int oldNumber = -1; + int oldBci = -1; for (String s : strings) { - - if (s.length() > 0 && Character.isDigit(s.charAt(0))) { - s = s.trim(); - int spaceIndex = s.indexOf(' '); - String numberString = s.substring(0, spaceIndex); - String tmpName = s.substring(spaceIndex + 1, s.length()); + s = s.trim(); + if (s.length() != 0) { + final Matcher matcher = instruction.matcher(s); + if (matcher.matches()) { + String bciString = matcher.group(1); + String opcode = matcher.group(2); + String operands = matcher.group(3).trim(); + String comment = matcher.group(4); + if (comment != null) { + comment = comment.trim(); + } - int number = -1; - number = Integer.parseInt(numberString); + int bci = Integer.parseInt(bciString); - // assert correct order of bytecodes - assert number > oldNumber; + // assert correct order of bytecodes + assert bci > oldBci; + + InputBytecode bc = new InputBytecode(bci, opcode, operands, comment); + bytecodes.add(bc); - InputBytecode bc = new InputBytecode(number, tmpName); - bytecodes.add(bc); - - for (InputMethod m : inlined) { - if (m.getBci() == number) { - bc.setInlined(m); - break; + for (InputMethod m : inlined) { + if (m.getBci() == bci) { + bc.setInlined(m); + break; + } } + } else { + System.out.println("no match: " + s); } } }
--- a/src/share/vm/classfile/systemDictionary.hpp Mon Jul 09 14:15:55 2012 +0200 +++ b/src/share/vm/classfile/systemDictionary.hpp Mon Jul 09 14:22:22 2012 +0200 @@ -186,13 +186,13 @@ template(Short_klass, java_lang_Short, Pre) \ template(Integer_klass, java_lang_Integer, Pre) \ template(Long_klass, java_lang_Long, Pre) \ - \ - /* Support for Graal */ \ + \ + /* Support for Graal */ \ template(GraalBitMap_klass, java_util_BitSet, Opt) \ - /* graal.hotspot */ \ + /* graal.hotspot */ \ template(HotSpotKlassOop_klass, com_oracle_graal_hotspot_HotSpotKlassOop, Opt) \ template(HotSpotProxy_klass, com_oracle_graal_hotspot_HotSpotProxy, Opt) \ - template(HotSpotTargetMethod_klass, com_oracle_graal_hotspot_HotSpotTargetMethod, Opt) \ + template(HotSpotCompilationResult_klass, com_oracle_graal_hotspot_HotSpotCompilationResult, Opt) \ template(HotSpotCodeInfo_klass, com_oracle_graal_hotspot_meta_HotSpotCodeInfo, Opt) \ template(HotSpotCompiledMethod_klass, com_oracle_graal_hotspot_meta_HotSpotCompiledMethod, Opt) \ template(HotSpotJavaType_klass, com_oracle_graal_hotspot_meta_HotSpotJavaType, Opt) \ @@ -200,7 +200,7 @@ template(HotSpotResolvedJavaField_klass, com_oracle_graal_hotspot_meta_HotSpotResolvedJavaField, Opt) \ template(HotSpotResolvedJavaMethod_klass, com_oracle_graal_hotspot_meta_HotSpotResolvedJavaMethod, Opt) \ template(HotSpotResolvedJavaType_klass, com_oracle_graal_hotspot_meta_HotSpotResolvedJavaType, Opt) \ - /* graal.api.code */ \ + /* graal.api.code */ \ template(Assumptions_klass, com_oracle_graal_api_code_Assumptions, Opt) \ template(Assumptions_ConcreteMethod_klass, com_oracle_graal_api_code_Assumptions_ConcreteMethod, Opt) \ template(Assumptions_ConcreteSubtype_klass, com_oracle_graal_api_code_Assumptions_ConcreteSubtype, Opt) \ @@ -221,7 +221,7 @@ template(RuntimeCall_klass, com_oracle_graal_api_code_RuntimeCall, Opt) \ template(StackSlot_klass, com_oracle_graal_api_code_StackSlot, Opt) \ template(VirtualObject_klass, com_oracle_graal_api_code_VirtualObject, Opt) \ - /* graal.api.meta */ \ + /* graal.api.meta */ \ template(Constant_klass, com_oracle_graal_api_meta_Constant, Opt) \ template(ExceptionHandler_klass, com_oracle_graal_api_meta_ExceptionHandler, Opt) \ template(Kind_klass, com_oracle_graal_api_meta_Kind, Opt) \
--- a/src/share/vm/classfile/vmSymbols.hpp Mon Jul 09 14:15:55 2012 +0200 +++ b/src/share/vm/classfile/vmSymbols.hpp Mon Jul 09 14:22:22 2012 +0200 @@ -267,15 +267,15 @@ NOT_LP64( do_alias(intptr_signature, int_signature) ) \ LP64_ONLY( do_alias(intptr_signature, long_signature) ) \ template(selectAlternative_signature, "(ZLjava/lang/invoke/MethodHandle;Ljava/lang/invoke/MethodHandle;)Ljava/lang/invoke/MethodHandle;") \ - \ - /* Support for Graal */ \ - template(java_util_BitSet, "java/util/BitSet") \ - /* graal.hotspot */ \ + \ + /* Support for Graal */ \ + template(java_util_BitSet, "java/util/BitSet") \ + /* graal.hotspot */ \ template(com_oracle_graal_hotspot_HotSpotGraalRuntime, "com/oracle/graal/hotspot/HotSpotGraalRuntime") \ template(com_oracle_graal_hotspot_HotSpotKlassOop, "com/oracle/graal/hotspot/HotSpotKlassOop") \ template(com_oracle_graal_hotspot_HotSpotOptions, "com/oracle/graal/hotspot/HotSpotOptions") \ template(com_oracle_graal_hotspot_HotSpotProxy, "com/oracle/graal/hotspot/HotSpotProxy") \ - template(com_oracle_graal_hotspot_HotSpotTargetMethod, "com/oracle/graal/hotspot/HotSpotTargetMethod") \ + template(com_oracle_graal_hotspot_HotSpotCompilationResult, "com/oracle/graal/hotspot/HotSpotCompilationResult") \ template(com_oracle_graal_hotspot_bridge_VMToCompiler, "com/oracle/graal/hotspot/bridge/VMToCompiler") \ template(com_oracle_graal_hotspot_meta_HotSpotCodeInfo, "com/oracle/graal/hotspot/meta/HotSpotCodeInfo") \ template(com_oracle_graal_hotspot_meta_HotSpotCompiledMethod, "com/oracle/graal/hotspot/meta/HotSpotCompiledMethod") \ @@ -284,7 +284,7 @@ template(com_oracle_graal_hotspot_meta_HotSpotResolvedJavaField, "com/oracle/graal/hotspot/meta/HotSpotResolvedJavaField") \ template(com_oracle_graal_hotspot_meta_HotSpotResolvedJavaMethod, "com/oracle/graal/hotspot/meta/HotSpotResolvedJavaMethod") \ template(com_oracle_graal_hotspot_meta_HotSpotResolvedJavaType, "com/oracle/graal/hotspot/meta/HotSpotResolvedJavaType") \ - /* graal.api.meta */ \ + /* graal.api.meta */ \ template(com_oracle_graal_api_meta_Constant, "com/oracle/graal/api/meta/Constant") \ template(com_oracle_graal_api_meta_ConstantPool, "com/oracle/graal/api/meta/ConstantPool") \ template(com_oracle_graal_api_meta_ExceptionHandler, "com/oracle/graal/api/meta/ExceptionHandler") \ @@ -293,7 +293,7 @@ template(com_oracle_graal_api_meta_Kind, "com/oracle/graal/api/meta/Kind") \ template(com_oracle_graal_api_meta_ResolvedJavaField, "com/oracle/graal/api/meta/ResolvedJavaField") \ template(com_oracle_graal_api_meta_Value, "com/oracle/graal/api/meta/Value") \ - /* graal.api.code */ \ + /* graal.api.code */ \ template(com_oracle_graal_api_code_Assumptions, "com/oracle/graal/api/code/Assumptions") \ template(com_oracle_graal_api_code_Assumptions_MethodContents, "com/oracle/graal/api/code/Assumptions$MethodContents") \ template(com_oracle_graal_api_code_Assumptions_ConcreteSubtype, "com/oracle/graal/api/code/Assumptions$ConcreteSubtype") \
--- a/src/share/vm/graal/graalCodeInstaller.cpp Mon Jul 09 14:15:55 2012 +0200 +++ b/src/share/vm/graal/graalCodeInstaller.cpp Mon Jul 09 14:22:22 2012 +0200 @@ -250,7 +250,7 @@ _env->set_oop_recorder(_oop_recorder); _env->set_dependencies(_dependencies); _dependencies = new Dependencies(_env); - Handle assumptions_handle = InstalledCode::assumptions(HotSpotTargetMethod::targetMethod(target_method)); + Handle assumptions_handle = InstalledCode::assumptions(HotSpotCompilationResult::comp(target_method)); if (!assumptions_handle.is_null()) { objArrayHandle assumptions(Thread::current(), (objArrayOop)Assumptions::list(assumptions_handle())); int length = assumptions->length(); @@ -288,7 +288,7 @@ } int stack_slots = _total_frame_size / HeapWordSize; // conversion to words - methodHandle method = getMethodFromHotSpotMethod(HotSpotTargetMethod::method(JNIHandles::resolve(target_method_obj))); + methodHandle method = getMethodFromHotSpotMethod(HotSpotCompilationResult::method(JNIHandles::resolve(target_method_obj))); nm = GraalEnv::register_method(method, -1, &_offsets, _custom_stack_area_offset, &buffer, stack_slots, _debug_recorder->_oopmaps, &_exception_handler_table, &_implicit_exception_table, GraalCompiler::instance(), _debug_recorder, _dependencies, NULL, -1, true, false, install_code); @@ -318,14 +318,14 @@ } void CodeInstaller::initialize_fields(oop target_method) { - _citarget_method = HotSpotTargetMethod::targetMethod(target_method); - _hotspot_method = HotSpotTargetMethod::method(target_method); + _citarget_method = HotSpotCompilationResult::comp(target_method); + _hotspot_method = HotSpotCompilationResult::method(target_method); if (_hotspot_method != NULL) { _parameter_count = getMethodFromHotSpotMethod(_hotspot_method)->size_of_parameters(); } - _name = HotSpotTargetMethod::name(target_method); - _sites = (arrayOop) HotSpotTargetMethod::sites(target_method); - _exception_handlers = (arrayOop) HotSpotTargetMethod::exceptionHandlers(target_method); + _name = HotSpotCompilationResult::name(target_method); + _sites = (arrayOop) HotSpotCompilationResult::sites(target_method); + _exception_handlers = (arrayOop) HotSpotCompilationResult::exceptionHandlers(target_method); _code = (arrayOop) InstalledCode::targetCode(_citarget_method); _code_size = InstalledCode::targetCodeSize(_citarget_method);
--- a/src/share/vm/graal/graalCompiler.cpp Mon Jul 09 14:15:55 2012 +0200 +++ b/src/share/vm/graal/graalCompiler.cpp Mon Jul 09 14:22:22 2012 +0200 @@ -273,7 +273,7 @@ HotSpotResolvedJavaType::set_accessFlags(obj, klass->access_flags().as_int()); HotSpotResolvedJavaType::set_isInterface(obj, klass->is_interface()); HotSpotResolvedJavaType::set_superCheckOffset(obj, klass->super_check_offset()); - HotSpotResolvedJavaType::set_prototypeHeader(obj, (jlong) klass->prototype_header()); + HotSpotResolvedJavaType::set_initialMarkWord(obj, (jlong) klass->prototype_header()); HotSpotResolvedJavaType::set_isInstanceClass(obj, klass->oop_is_instance()); if (klass->oop_is_javaArray()) {
--- a/src/share/vm/graal/graalCompilerToVM.cpp Mon Jul 09 14:15:55 2012 +0200 +++ b/src/share/vm/graal/graalCompilerToVM.cpp Mon Jul 09 14:22:22 2012 +0200 @@ -790,6 +790,7 @@ set_int(env, config, "vmPageSize", os::vm_page_size()); set_int(env, config, "stackShadowPages", StackShadowPages); set_int(env, config, "hubOffset", oopDesc::klass_offset_in_bytes()); + set_int(env, config, "markOffset", oopDesc::mark_offset_in_bytes()); set_int(env, config, "superCheckOffsetOffset", in_bytes(Klass::super_check_offset_offset())); set_int(env, config, "secondarySuperCacheOffset", in_bytes(Klass::secondary_super_cache_offset())); set_int(env, config, "secondarySupersOffset", in_bytes(Klass::secondary_supers_offset())); @@ -803,7 +804,15 @@ set_int(env, config, "threadExceptionOopOffset", in_bytes(JavaThread::exception_oop_offset())); set_int(env, config, "threadExceptionPcOffset", in_bytes(JavaThread::exception_pc_offset())); set_int(env, config, "threadMultiNewArrayStorageOffset", in_bytes(JavaThread::graal_multinewarray_storage_offset())); + set_long(env, config, "safepointPollingAddress", (jlong)(os::get_polling_page() + (SafepointPollOffset % os::vm_page_size()))); + set_boolean(env, config, "isPollingPageFar", Assembler::is_polling_page_far()); set_int(env, config, "classMirrorOffset", in_bytes(Klass::java_mirror_offset())); + set_int(env, config, "runtimeCallStackSize", (jint)frame::arg_reg_save_area_bytes); + set_int(env, config, "klassModifierFlagsOffset", in_bytes(Klass::modifier_flags_offset())); + set_int(env, config, "klassOopOffset", java_lang_Class::klass_offset_in_bytes()); + set_int(env, config, "graalMirrorKlassOffset", in_bytes(Klass::graal_mirror_offset())); + set_int(env, config, "nmethodEntryOffset", nmethod::verified_entry_point_offset()); + set_int(env, config, "methodCompiledEntryOffset", in_bytes(methodOopDesc::from_compiled_offset())); set_int(env, config, "methodDataOopDataOffset", in_bytes(methodDataOopDesc::data_offset())); set_int(env, config, "methodDataOopTrapHistoryOffset", in_bytes(methodDataOopDesc::trap_history_offset())); @@ -823,14 +832,10 @@ set_long(env, config, "debugStub", VmIds::addStub((address)warning)); set_long(env, config, "instanceofStub", VmIds::addStub(Runtime1::entry_for(Runtime1::slow_subtype_check_id))); - set_long(env, config, "verifyOopStub", VmIds::addStub(Runtime1::entry_for(Runtime1::graal_verify_oop_id))); set_long(env, config, "newInstanceStub", VmIds::addStub(Runtime1::entry_for(newInstanceStub))); set_long(env, config, "newTypeArrayStub", VmIds::addStub(Runtime1::entry_for(Runtime1::new_type_array_id))); set_long(env, config, "newObjectArrayStub", VmIds::addStub(Runtime1::entry_for(Runtime1::new_object_array_id))); set_long(env, config, "newMultiArrayStub", VmIds::addStub(Runtime1::entry_for(Runtime1::new_multi_array_id))); - set_long(env, config, "loadKlassStub", VmIds::addStub(Runtime1::entry_for(Runtime1::load_klass_patching_id))); - set_long(env, config, "accessFieldStub", VmIds::addStub(Runtime1::entry_for(Runtime1::access_field_patching_id))); - set_long(env, config, "resolveStaticCallStub", VmIds::addStub(SharedRuntime::get_resolve_static_call_stub())); set_long(env, config, "inlineCacheMissStub", VmIds::addStub(SharedRuntime::get_ic_miss_stub())); set_long(env, config, "handleExceptionStub", VmIds::addStub(Runtime1::entry_for(Runtime1::handle_exception_nofpu_id))); set_long(env, config, "handleDeoptStub", VmIds::addStub(SharedRuntime::deopt_blob()->unpack())); @@ -838,16 +843,8 @@ set_long(env, config, "monitorExitStub", VmIds::addStub(Runtime1::entry_for(Runtime1::monitorexit_id))); set_long(env, config, "fastMonitorEnterStub", VmIds::addStub(Runtime1::entry_for(Runtime1::graal_monitorenter_id))); set_long(env, config, "fastMonitorExitStub", VmIds::addStub(Runtime1::entry_for(Runtime1::graal_monitorexit_id))); - set_long(env, config, "safepointPollingAddress", (jlong)(os::get_polling_page() + (SafepointPollOffset % os::vm_page_size()))); - set_int(env, config, "runtimeCallStackSize", (jint)frame::arg_reg_save_area_bytes); - set_int(env, config, "klassModifierFlagsOffset", in_bytes(Klass::modifier_flags_offset())); - set_int(env, config, "graalMirrorKlassOffset", in_bytes(Klass::graal_mirror_offset())); - set_int(env, config, "klassOopOffset", java_lang_Class::klass_offset_in_bytes()); - set_int(env, config, "methodCompiledEntryOffset", in_bytes(methodOopDesc::from_compiled_offset())); + set_long(env, config, "verifyOopStub", VmIds::addStub(Runtime1::entry_for(Runtime1::graal_verify_oop_id))); - set_boolean(env, config, "isPollingPageFar", Assembler::is_polling_page_far()); - - set_int(env, config, "nmethodEntryOffset", nmethod::verified_entry_point_offset()); BarrierSet* bs = Universe::heap()->barrier_set(); switch (bs->kind()) { @@ -874,22 +871,16 @@ break; } - jintArray arrayOffsets = env->NewIntArray(basicTypeCount); - for (int i=0; i<basicTypeCount; i++) { - jint offset = arrayOopDesc::base_offset_in_bytes(basicTypes[i]); - env->SetIntArrayRegion(arrayOffsets, i, 1, &offset); - } - set_int_array(env, config, "arrayOffsets", arrayOffsets); set_int(env, config, "arrayClassElementOffset", in_bytes(objArrayKlass::element_klass_offset())); return config; } -// public HotSpotCompiledMethod installMethod(HotSpotTargetMethod targetMethod, boolean installCode); -JNIEXPORT jobject JNICALL Java_com_oracle_graal_hotspot_bridge_CompilerToVMImpl_installMethod(JNIEnv *jniEnv, jobject, jobject targetMethod, jboolean install_code, jobject info) { +// public HotSpotCompiledMethod installMethod(HotSpotCompilationResult comp, boolean installCode); +JNIEXPORT jobject JNICALL Java_com_oracle_graal_hotspot_bridge_CompilerToVMImpl_installMethod(JNIEnv *jniEnv, jobject, jobject comp, jboolean install_code, jobject info) { VM_ENTRY_MARK; ResourceMark rm; HandleMark hm; - Handle targetMethodHandle = JNIHandles::resolve(targetMethod); + Handle targetMethodHandle = JNIHandles::resolve(comp); nmethod* nm = NULL; Arena arena; ciEnv env(&arena); @@ -908,7 +899,7 @@ Handle obj = instanceKlass::cast(HotSpotCompiledMethod::klass())->allocate_permanent_instance(CHECK_NULL); assert(obj() != NULL, "must succeed in allocating instance"); HotSpotCompiledMethod::set_nmethod(obj, (jlong) nm); - HotSpotCompiledMethod::set_method(obj, HotSpotTargetMethod::method(targetMethod)); + HotSpotCompiledMethod::set_method(obj, HotSpotCompilationResult::method(comp)); nm->set_graal_compiled_method(obj()); return JNIHandles::make_local(obj()); } else { @@ -934,25 +925,6 @@ return JNIHandles::make_local(result()); } -// public String disassembleJava(HotSpotResolvedJavaMethod method); -JNIEXPORT jobject JNICALL Java_com_oracle_graal_hotspot_bridge_CompilerToVMImpl_disassembleJava(JNIEnv *env, jobject, jobject hotspot_method) { - TRACE_graal_3("CompilerToVM::disassembleJava"); - - // Important: The bytecode printing functions are all NOT PRODUCT code, so this method returns an empty string for a product VM build. - - VM_ENTRY_MARK; - ResourceMark rm; - HandleMark hm; - - methodHandle method = getMethodFromHotSpotMethod(hotspot_method); - // Note: cannot use resource-allocated stringStream because print_code_on has its own ResourceMark. - bufferedStream(st); - method->print_codes_on(&st); - - Handle result = java_lang_String::create_from_platform_dependent_str(st.as_string(), CHECK_NULL); - return JNIHandles::make_local(result()); -} - // public StackTraceElement JavaMethod_toStackTraceElement(HotSpotResolvedJavaMethod method, int bci); JNIEXPORT jobject JNICALL Java_com_oracle_graal_hotspot_bridge_CompilerToVMImpl_JavaMethod_1toStackTraceElement(JNIEnv *env, jobject, jobject hotspot_method, int bci) { TRACE_graal_3("CompilerToVM::JavaMethod_toStackTraceElement"); @@ -1094,15 +1066,15 @@ #define RESOLVED_FIELD "Lcom/oracle/graal/api/meta/ResolvedJavaField;" #define CONSTANT_POOL "Lcom/oracle/graal/api/meta/ConstantPool;" #define EXCEPTION_HANDLERS "[Lcom/oracle/graal/api/meta/ExceptionHandler;" -#define TARGET_METHOD "Lcom/oracle/graal/hotspot/HotSpotTargetMethod;" +#define HS_COMP_RESULT "Lcom/oracle/graal/hotspot/HotSpotCompilationResult;" #define CONFIG "Lcom/oracle/graal/hotspot/HotSpotVMConfig;" #define HS_METHOD "Lcom/oracle/graal/hotspot/meta/HotSpotMethod;" #define HS_COMP_METHOD "Lcom/oracle/graal/hotspot/meta/HotSpotCompiledMethod;" #define HS_CODE_INFO "Lcom/oracle/graal/hotspot/meta/HotSpotCodeInfo;" #define METHOD_DATA "Lcom/oracle/graal/hotspot/meta/HotSpotMethodData;" -#define CI_CONSTANT "Lcom/oracle/graal/api/meta/Constant;" -#define CI_KIND "Lcom/oracle/graal/api/meta/Kind;" -#define CI_RUNTIME_CALL "Lcom/oracle/graal/api/code/RuntimeCall;" +#define CONSTANT "Lcom/oracle/graal/api/meta/Constant;" +#define KIND "Lcom/oracle/graal/api/meta/Kind;" +#define RUNTIME_CALL "Lcom/oracle/graal/api/code/RuntimeCall;" #define STRING "Ljava/lang/String;" #define OBJECT "Ljava/lang/Object;" #define CLASS "Ljava/lang/Class;" @@ -1119,12 +1091,12 @@ {CC"JavaMethod_invocationCount", CC"("RESOLVED_METHOD")I", FN_PTR(JavaMethod_1invocationCount)}, {CC"JavaMethod_hasCompiledCode", CC"("RESOLVED_METHOD")Z", FN_PTR(JavaMethod_1hasCompiledCode)}, {CC"JavaMethod_getCompiledCodeSize", CC"("RESOLVED_METHOD")I", FN_PTR(JavaMethod_1getCompiledCodeSize)}, - {CC"Signature_lookupType", CC"("STRING RESOLVED_TYPE"Z)"TYPE, FN_PTR(Signature_1lookupType)}, - {CC"ConstantPool_lookupConstant", CC"("RESOLVED_TYPE"I)"OBJECT, FN_PTR(ConstantPool_1lookupConstant)}, - {CC"ConstantPool_lookupMethod", CC"("RESOLVED_TYPE"IB)"METHOD, FN_PTR(ConstantPool_1lookupMethod)}, - {CC"ConstantPool_lookupType", CC"("RESOLVED_TYPE"I)"TYPE, FN_PTR(ConstantPool_1lookupType)}, - {CC"ConstantPool_loadReferencedType", CC"("RESOLVED_TYPE"IB)V", FN_PTR(ConstantPool_1loadReferencedType)}, - {CC"ConstantPool_lookupField", CC"("RESOLVED_TYPE"IB)"FIELD, FN_PTR(ConstantPool_1lookupField)}, + {CC"Signature_lookupType", CC"("STRING RESOLVED_TYPE"Z)"TYPE, FN_PTR(Signature_1lookupType)}, + {CC"ConstantPool_lookupConstant", CC"("RESOLVED_TYPE"I)"OBJECT, FN_PTR(ConstantPool_1lookupConstant)}, + {CC"ConstantPool_lookupMethod", CC"("RESOLVED_TYPE"IB)"METHOD, FN_PTR(ConstantPool_1lookupMethod)}, + {CC"ConstantPool_lookupType", CC"("RESOLVED_TYPE"I)"TYPE, FN_PTR(ConstantPool_1lookupType)}, + {CC"ConstantPool_loadReferencedType", CC"("RESOLVED_TYPE"IB)V", FN_PTR(ConstantPool_1loadReferencedType)}, + {CC"ConstantPool_lookupField", CC"("RESOLVED_TYPE"IB)"FIELD, FN_PTR(ConstantPool_1lookupField)}, {CC"JavaType_resolveMethodImpl", CC"("RESOLVED_TYPE STRING STRING")"METHOD, FN_PTR(JavaType_3resolveMethodImpl)}, {CC"JavaType_isSubtypeOf", CC"("RESOLVED_TYPE TYPE")Z", FN_PTR(JavaType_2isSubtypeOf)}, {CC"JavaType_leastCommonAncestor", CC"("RESOLVED_TYPE RESOLVED_TYPE")"TYPE, FN_PTR(JavaType_2leastCommonAncestor)}, @@ -1134,19 +1106,18 @@ {CC"JavaType_arrayOf", CC"("RESOLVED_TYPE")"TYPE, FN_PTR(JavaType_1arrayOf)}, {CC"JavaType_fields", CC"("RESOLVED_TYPE")["RESOLVED_FIELD, FN_PTR(JavaType_1fields)}, {CC"JavaType_isInitialized", CC"("RESOLVED_TYPE")Z", FN_PTR(JavaType_1isInitialized)}, - {CC"getPrimitiveArrayType", CC"("CI_KIND")"TYPE, FN_PTR(getPrimitiveArrayType)}, - {CC"getMaxCallTargetOffset", CC"("CI_RUNTIME_CALL")J", FN_PTR(getMaxCallTargetOffset)}, - {CC"getType", CC"("CLASS")"TYPE, FN_PTR(getType)}, - {CC"getConfiguration", CC"()"CONFIG, FN_PTR(getConfiguration)}, - {CC"installMethod", CC"("TARGET_METHOD"Z"HS_CODE_INFO")"HS_COMP_METHOD, FN_PTR(installMethod)}, - {CC"disassembleNative", CC"([BJ)"STRING, FN_PTR(disassembleNative)}, - {CC"disassembleJava", CC"("RESOLVED_METHOD")"STRING, FN_PTR(disassembleJava)}, + {CC"getPrimitiveArrayType", CC"("KIND")"TYPE, FN_PTR(getPrimitiveArrayType)}, + {CC"getMaxCallTargetOffset", CC"("RUNTIME_CALL")J", FN_PTR(getMaxCallTargetOffset)}, + {CC"getType", CC"("CLASS")"TYPE, FN_PTR(getType)}, + {CC"getConfiguration", CC"()"CONFIG, FN_PTR(getConfiguration)}, + {CC"installMethod", CC"("HS_COMP_RESULT"Z"HS_CODE_INFO")"HS_COMP_METHOD, FN_PTR(installMethod)}, + {CC"disassembleNative", CC"([BJ)"STRING, FN_PTR(disassembleNative)}, {CC"JavaMethod_toStackTraceElement", CC"("RESOLVED_METHOD"I)"STACK_TRACE_ELEMENT, FN_PTR(JavaMethod_1toStackTraceElement)}, - {CC"executeCompiledMethod", CC"("HS_COMP_METHOD OBJECT OBJECT OBJECT")"OBJECT, FN_PTR(executeCompiledMethod)}, - {CC"executeCompiledMethodVarargs", CC"("HS_COMP_METHOD "["OBJECT")"OBJECT, FN_PTR(executeCompiledMethodVarargs)}, + {CC"executeCompiledMethod", CC"("HS_COMP_METHOD OBJECT OBJECT OBJECT")"OBJECT, FN_PTR(executeCompiledMethod)}, + {CC"executeCompiledMethodVarargs", CC"("HS_COMP_METHOD "["OBJECT")"OBJECT, FN_PTR(executeCompiledMethodVarargs)}, {CC"JavaMethod_vtableEntryOffset", CC"("RESOLVED_METHOD")I", FN_PTR(JavaMethod_vtableEntryOffset)}, - {CC"getDeoptedLeafGraphIds", CC"()[J", FN_PTR(getDeoptedLeafGraphIds)}, - {CC"decodePC", CC"(J)"STRING, FN_PTR(decodePC)}, + {CC"getDeoptedLeafGraphIds", CC"()[J", FN_PTR(getDeoptedLeafGraphIds)}, + {CC"decodePC", CC"(J)"STRING, FN_PTR(decodePC)}, }; int CompilerToVM_methods_count() {
--- a/src/share/vm/graal/graalJavaAccess.hpp Mon Jul 09 14:15:55 2012 +0200 +++ b/src/share/vm/graal/graalJavaAccess.hpp Mon Jul 09 14:22:22 2012 +0200 @@ -52,7 +52,7 @@ oop_field(HotSpotResolvedJavaType, javaMirror, "Ljava/lang/Class;") \ oop_field(HotSpotResolvedJavaType, simpleName, "Ljava/lang/String;") \ int_field(HotSpotResolvedJavaType, accessFlags) \ - long_field(HotSpotResolvedJavaType, prototypeHeader) \ + long_field(HotSpotResolvedJavaType, initialMarkWord) \ boolean_field(HotSpotResolvedJavaType, hasFinalizer) \ boolean_field(HotSpotResolvedJavaType, hasFinalizableSubclass) \ int_field(HotSpotResolvedJavaType, superCheckOffset) \ @@ -98,12 +98,12 @@ start_class(HotSpotProxy) \ static_oop_field(HotSpotProxy, DUMMY_CONSTANT_OBJ, "Ljava/lang/Long;") \ end_class \ - start_class(HotSpotTargetMethod) \ - oop_field(HotSpotTargetMethod, targetMethod, "Lcom/oracle/graal/api/code/CompilationResult;") \ - oop_field(HotSpotTargetMethod, method, "Lcom/oracle/graal/hotspot/meta/HotSpotResolvedJavaMethod;") \ - oop_field(HotSpotTargetMethod, name, "Ljava/lang/String;") \ - oop_field(HotSpotTargetMethod, sites, "[Lcom/oracle/graal/api/code/CompilationResult$Site;") \ - oop_field(HotSpotTargetMethod, exceptionHandlers, "[Lcom/oracle/graal/api/code/CompilationResult$ExceptionHandler;") \ + start_class(HotSpotCompilationResult) \ + oop_field(HotSpotCompilationResult, comp, "Lcom/oracle/graal/api/code/CompilationResult;") \ + oop_field(HotSpotCompilationResult, method, "Lcom/oracle/graal/hotspot/meta/HotSpotResolvedJavaMethod;") \ + oop_field(HotSpotCompilationResult, name, "Ljava/lang/String;") \ + oop_field(HotSpotCompilationResult, sites, "[Lcom/oracle/graal/api/code/CompilationResult$Site;") \ + oop_field(HotSpotCompilationResult, exceptionHandlers, "[Lcom/oracle/graal/api/code/CompilationResult$ExceptionHandler;") \ end_class \ start_class(ExceptionHandler) \ int_field(ExceptionHandler, startBCI) \
--- a/src/share/vm/graal/graalVMToInterpreter.cpp Mon Jul 09 14:15:55 2012 +0200 +++ b/src/share/vm/graal/graalVMToInterpreter.cpp Mon Jul 09 14:22:22 2012 +0200 @@ -237,7 +237,7 @@ if (is_java_primitive(expected_result_type)) { unbox_primitive(&boxed_result, result); } else if (expected_result_type == T_OBJECT || expected_result_type == T_ARRAY) { - result->set_jobject(result->get_jobject()); + result->set_jobject(boxed_result.get_jobject()); } }
--- a/src/share/vm/runtime/javaCalls.cpp Mon Jul 09 14:15:55 2012 +0200 +++ b/src/share/vm/runtime/javaCalls.cpp Mon Jul 09 14:22:22 2012 +0200 @@ -445,6 +445,7 @@ if (thread->high_level_interpreter_in_vm() && !method->is_native() && Interpreter::contains(entry_point)) { assert(nm == NULL || !nm->is_alive(), "otherwise nm should be invoked"); VMToInterpreter::execute(result, m, args, result->get_type(), thread); + oop_result_flag = false; // result already holds the correct value } else #endif // do call
--- a/visualizer/Data/src/com/sun/hotspot/igv/data/InputMethod.java Mon Jul 09 14:15:55 2012 +0200 +++ b/visualizer/Data/src/com/sun/hotspot/igv/data/InputMethod.java Mon Jul 09 14:22:22 2012 +0200 @@ -121,7 +121,11 @@ String tmpName = s.substring(spaceIndex + 1, s.length()); int number = -1; - number = Integer.parseInt(numberString); + try { + number = Integer.parseInt(numberString); + } catch (NumberFormatException e) { + // nothing to do... + } // assert correct order of bytecodes assert number > oldNumber;