# HG changeset patch # User Christian Haeubl # Date 1358323704 -3600 # Node ID 42b6e090588193f3538a2d922ec255dc205dc6c9 # Parent 36dafe48bc38d463cb767ebada66e859b61374b1# Parent 6ad818b8892e655ff3b0eb6b6a0e245fc379a052 Merge. diff -r 36dafe48bc38 -r 42b6e0905881 graal/com.oracle.graal.alloc/src/com/oracle/graal/alloc/ComputeBlockOrder.java --- a/graal/com.oracle.graal.alloc/src/com/oracle/graal/alloc/ComputeBlockOrder.java Wed Jan 16 09:05:48 2013 +0100 +++ b/graal/com.oracle.graal.alloc/src/com/oracle/graal/alloc/ComputeBlockOrder.java Wed Jan 16 09:08:24 2013 +0100 @@ -25,9 +25,6 @@ import java.util.*; -import com.oracle.graal.debug.*; -import com.oracle.graal.graph.*; -import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.cfg.*; /** @@ -35,29 +32,154 @@ * and the machine code generator. */ public final class ComputeBlockOrder { - private int blockCount; private List linearScanOrder; private List codeEmittingOrder; - private final BitSet visitedBlocks; // used for recursive processing of blocks - private final BitSet activeBlocks; // used for recursive processing of blocks - private final int[] forwardBranches; // number of incoming forward branches for each block - private final List workList; // temporary list (used in markLoops and computeOrder) - private final List loopHeaders; - private final boolean reorderLoops; + + private Comparator blockComparator = new Comparator() { + @Override + public int compare(Block o1, Block o2) { + // Loop blocks before any loop exit block. + int diff = o2.getLoopDepth() - o1.getLoopDepth(); + if (diff != 0) { + return diff; + } + + // Blocks with high probability before blocks with low probability. + if (o1.getBeginNode().probability() > o2.getBeginNode().probability()) { + return -1; + } else { + return 1; + } + }}; + + public ComputeBlockOrder(int maxBlockId, @SuppressWarnings("unused") int loopCount, Block startBlock, @SuppressWarnings("unused") boolean reorderLoops) { + + List newLinearScanOrder = new ArrayList<>(); + List order = new ArrayList<>(); + PriorityQueue worklist = new PriorityQueue<>(10, blockComparator); + BitSet orderedBlocks = new BitSet(maxBlockId); + orderedBlocks.set(startBlock.getId()); + worklist.add(startBlock); + computeCodeEmittingOrder(order, worklist, orderedBlocks); + codeEmittingOrder = order; + + orderedBlocks.clear(); + orderedBlocks.set(startBlock.getId()); + worklist.add(startBlock); + computeNewLinearScanOrder(newLinearScanOrder, worklist, orderedBlocks); + + assert order.size() == newLinearScanOrder.size() : codeEmittingOrder.size() + " vs " + newLinearScanOrder.size(); + linearScanOrder = newLinearScanOrder; + } + + private void computeCodeEmittingOrder(List order, PriorityQueue worklist, BitSet orderedBlocks) { + while (!worklist.isEmpty()) { + Block nextImportantPath = worklist.poll(); + addImportantPath(nextImportantPath, order, worklist, orderedBlocks); + } + } + + private void computeNewLinearScanOrder(List order, PriorityQueue worklist, BitSet orderedBlocks) { + while (!worklist.isEmpty()) { + Block nextImportantPath = worklist.poll(); + addImportantLinearScanOrderPath(nextImportantPath, order, worklist, orderedBlocks); + } + } + + private void addImportantLinearScanOrderPath(Block block, List order, PriorityQueue worklist, BitSet orderedBlocks) { + order.add(block); + + Block bestSucc = null; + double bestSuccProb = 0; + + for (Block succ : block.getSuccessors()) { + if (!orderedBlocks.get(succ.getId()) && succ.getLoopDepth() >= block.getLoopDepth()) { + double curProb = succ.getBeginNode().probability(); + if (curProb >= bestSuccProb) { + bestSuccProb = curProb; + bestSucc = succ; + } + assert curProb >= 0 : curProb; + } + } - public ComputeBlockOrder(int maxBlockId, int loopCount, Block startBlock, boolean reorderLoops) { - loopHeaders = new ArrayList<>(loopCount); - while (loopHeaders.size() < loopCount) { - loopHeaders.add(null); + for (Block succ : block.getSuccessors()) { + if (!orderedBlocks.get(succ.getId())) { + if (succ != bestSucc) { + orderedBlocks.set(succ.getId()); + worklist.add(succ); + } + } + } + + if (bestSucc != null) { + if (!bestSucc.isLoopHeader() && bestSucc.getPredecessors().size() > 1) { + // We are at a merge. Check probabilities of predecessors that are not yet scheduled. + double unscheduledSum = 0.0; + double scheduledSum = 0.0; + for (Block pred : bestSucc.getPredecessors()) { + if (!orderedBlocks.get(pred.getId())) { + unscheduledSum += pred.getBeginNode().probability(); + } else { + scheduledSum += pred.getBeginNode().probability(); + } + } + + if (unscheduledSum > 0.0 && unscheduledSum > scheduledSum / 10) { + return; + } + } + orderedBlocks.set(bestSucc.getId()); + addImportantLinearScanOrderPath(bestSucc, order, worklist, orderedBlocks); + } + } + + private void addImportantPath(Block block, List order, PriorityQueue worklist, BitSet orderedBlocks) { + if (!skipLoopHeader(block)) { + if (block.isLoopHeader()) { + block.align = true; + } + order.add(block); } - visitedBlocks = new BitSet(maxBlockId); - activeBlocks = new BitSet(maxBlockId); - forwardBranches = new int[maxBlockId]; - workList = new ArrayList<>(8); - this.reorderLoops = reorderLoops; + if (block.isLoopEnd() && skipLoopHeader(block.getLoop().header)) { + order.add(block.getLoop().header); + for (Block succ : block.getLoop().header.getSuccessors()) { + if (succ.getLoopDepth() == block.getLoopDepth()) { + succ.align = true; + } + } + } + Block bestSucc = null; + double bestSuccProb = 0; - countEdges(startBlock, null); - computeOrder(startBlock); + for (Block succ : block.getSuccessors()) { + if (!orderedBlocks.get(succ.getId()) && succ.getLoopDepth() >= block.getLoopDepth()) { + double curProb = succ.getBeginNode().probability(); + if (curProb >= bestSuccProb) { + bestSuccProb = curProb; + bestSucc = succ; + } + assert curProb >= 0 : curProb; + } + } + + for (Block succ : block.getSuccessors()) { + if (!orderedBlocks.get(succ.getId())) { + if (succ != bestSucc) { + orderedBlocks.set(succ.getId()); + worklist.add(succ); + } + } + } + + if (bestSucc != null) { + orderedBlocks.set(bestSucc.getId()); + addImportantPath(bestSucc, order, worklist, orderedBlocks); + } + } + + private static boolean skipLoopHeader(Block bestSucc) { + return (bestSucc.isLoopHeader() && !bestSucc.isLoopEnd() && bestSucc.getLoop().loopBegin().loopEnds().count() == 1); } /** @@ -75,209 +197,4 @@ public List codeEmittingOrder() { return codeEmittingOrder; } - - private boolean isVisited(Block b) { - return visitedBlocks.get(b.getId()); - } - - private boolean isActive(Block b) { - return activeBlocks.get(b.getId()); - } - - private void setVisited(Block b) { - assert !isVisited(b); - visitedBlocks.set(b.getId()); - } - - private void setActive(Block b) { - assert !isActive(b); - activeBlocks.set(b.getId()); - } - - private void clearActive(Block b) { - assert isActive(b); - activeBlocks.clear(b.getId()); - } - - private void incForwardBranches(Block b) { - forwardBranches[b.getId()]++; - } - - private int decForwardBranches(Block b) { - return --forwardBranches[b.getId()]; - } - - /** - * Traverses the CFG to analyze block and edge info. The analysis performed is: - * - * 1. Count of total number of blocks. - * 2. Count of all incoming edges and backward incoming edges. - * 3. Number loop header blocks. - * 4. Create a list with all loop end blocks. - */ - private void countEdges(Block cur, Block parent) { - Debug.log("Counting edges for block B%d%s", cur.getId(), parent == null ? "" : " coming from B" + parent.getId()); - - if (isActive(cur)) { - return; - } - - // increment number of incoming forward branches - incForwardBranches(cur); - - if (isVisited(cur)) { - return; - } - - blockCount++; - setVisited(cur); - setActive(cur); - - // recursive call for all successors - for (int i = cur.numberOfSux() - 1; i >= 0; i--) { - countEdges(cur.suxAt(i), cur); - } - - clearActive(cur); - - Debug.log("Finished counting edges for block B%d", cur.getId()); - } - - private static int computeWeight(Block cur) { - - // limit loop-depth to 15 bit (only for security reason, it will never be so big) - int weight = (cur.getLoopDepth() & 0x7FFF) << 16; - - int curBit = 15; - - // loop end blocks (blocks that end with a backward branch) are added - // after all other blocks of the loop. - if (!cur.isLoopEnd()) { - weight |= 1 << curBit; - } - curBit--; - - // exceptions handlers are added as late as possible - if (!cur.isExceptionEntry()) { - weight |= 1 << curBit; - } - curBit--; - - // guarantee that weight is > 0 - weight |= 1; - - assert curBit >= 0 : "too many flags"; - assert weight > 0 : "weight cannot become negative"; - - return weight; - } - - private boolean readyForProcessing(Block cur) { - // Discount the edge just traveled. - // When the number drops to zero, all forward branches were processed - if (decForwardBranches(cur) != 0) { - return false; - } - - assert !linearScanOrder.contains(cur) : "block already processed (block can be ready only once)"; - assert !workList.contains(cur) : "block already in work-list (block can be ready only once)"; - return true; - } - - private void sortIntoWorkList(Block cur) { - assert !workList.contains(cur) : "block already in work list"; - - int curWeight = computeWeight(cur); - - // the linearScanNumber is used to cache the weight of a block - cur.linearScanNumber = curWeight; - - workList.add(null); // provide space for new element - - int insertIdx = workList.size() - 1; - while (insertIdx > 0 && workList.get(insertIdx - 1).linearScanNumber > curWeight) { - workList.set(insertIdx, workList.get(insertIdx - 1)); - insertIdx--; - } - workList.set(insertIdx, cur); - - if (Debug.isLogEnabled()) { - Debug.log("Sorted B%d into worklist. new worklist:", cur.getId()); - for (int i = 0; i < workList.size(); i++) { - Debug.log(String.format("%8d B%02d weight:%6x", i, workList.get(i).getId(), workList.get(i).linearScanNumber)); - } - } - - for (int i = 0; i < workList.size(); i++) { - assert workList.get(i).linearScanNumber > 0 : "weight not set"; - assert i == 0 || workList.get(i - 1).linearScanNumber <= workList.get(i).linearScanNumber : "incorrect order in worklist"; - } - } - - private void appendBlock(Block cur) { - Debug.log("appending block B%d (weight 0x%06x) to linear-scan order", cur.getId(), cur.linearScanNumber); - assert !linearScanOrder.contains(cur) : "cannot add the same block twice"; - - cur.linearScanNumber = linearScanOrder.size(); - linearScanOrder.add(cur); - - if (cur.isLoopEnd() && cur.isLoopHeader()) { - codeEmittingOrder.add(cur); - } else { - if (!cur.isLoopHeader() || ((LoopBeginNode) cur.getBeginNode()).loopEnds().count() > 1 || !reorderLoops) { - codeEmittingOrder.add(cur); - - if (cur.isLoopEnd() && reorderLoops) { - Block loopHeader = loopHeaders.get(cur.getLoop().index); - if (loopHeader != null) { - codeEmittingOrder.add(loopHeader); - - for (int i = 0; i < loopHeader.numberOfSux(); i++) { - Block succ = loopHeader.suxAt(i); - if (succ.getLoopDepth() == loopHeader.getLoopDepth()) { - succ.align = true; - } - } - } - } - } else { - loopHeaders.set(cur.getLoop().index, cur); - } - } - } - - private void checkAndSortIntoWorkList(Block b) { - if (readyForProcessing(b)) { - sortIntoWorkList(b); - } - } - - private void computeOrder(Block startBlock) { - // the start block is always the first block in the linear scan order - linearScanOrder = new ArrayList<>(blockCount); - - codeEmittingOrder = new ArrayList<>(blockCount); - - // start processing with standard entry block - assert workList.isEmpty() : "list must be empty before processing"; - - assert readyForProcessing(startBlock); - sortIntoWorkList(startBlock); - - do { - Block cur = workList.remove(workList.size() - 1); - appendBlock(cur); - - Node endNode = cur.getEndNode(); - if (endNode instanceof IfNode && ((IfNode) endNode).probability() < 0.5) { - assert cur.numberOfSux() == 2; - checkAndSortIntoWorkList(cur.suxAt(1)); - checkAndSortIntoWorkList(cur.suxAt(0)); - } else { - for (Block sux : cur.getSuccessors()) { - checkAndSortIntoWorkList(sux); - } - } - } while (workList.size() > 0); - } } diff -r 36dafe48bc38 -r 42b6e0905881 graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/LineNumberTable.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/LineNumberTable.java Wed Jan 16 09:08:24 2013 +0100 @@ -0,0 +1,30 @@ +/* + * 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.api.meta; + + +public interface LineNumberTable { + int[] getLineNumberEntries(); + int[] getBciEntries(); + int getLineNumber(int bci); +} diff -r 36dafe48bc38 -r 42b6e0905881 graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/MetaAccessProvider.java --- a/graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/MetaAccessProvider.java Wed Jan 16 09:05:48 2013 +0100 +++ b/graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/MetaAccessProvider.java Wed Jan 16 09:08:24 2013 +0100 @@ -60,6 +60,13 @@ ResolvedJavaType lookupJavaType(Constant constant); /** + * Parses a method + * descriptor into a {@link Signature}. The behavior of this method is undefined if + * the method descriptor is not well formed. + */ + Signature parseMethodDescriptor(String methodDescriptor); + + /** * Compares two constants for equality. * This is used instead of {@link Constant#equals(Object)} in case the runtime * has an interpretation for object equality other than {@code x.asObject() == y.asObject()}. diff -r 36dafe48bc38 -r 42b6e0905881 graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/MetaUtil.java --- a/graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/MetaUtil.java Wed Jan 16 09:05:48 2013 +0100 +++ b/graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/MetaUtil.java Wed Jan 16 09:08:24 2013 +0100 @@ -494,23 +494,6 @@ } /** - * Converts a {@link Signature} to internal representation, i.e., the signature - *
(int, String, double)void
is converted to
(ILjava/lang/String;D)V
. - * - * @param sig the {@link Signature} to be converted. - * - * @return the signature's internal representation as a string. - */ - public static String signatureToInternal(Signature sig) { - StringBuilder sb = new StringBuilder("("); - for (int i = 0; i < sig.getParameterCount(false); ++i) { - sb.append(sig.getParameterType(i, null).getName()); - } - sb.append(')').append(sig.getReturnType(null).getName()); - return sb.toString(); - } - - /** * Formats some profiling information associated as a string. * * @param info the profiling info to format diff -r 36dafe48bc38 -r 42b6e0905881 graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/ResolvedJavaMethod.java --- a/graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/ResolvedJavaMethod.java Wed Jan 16 09:05:48 2013 +0100 +++ b/graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/ResolvedJavaMethod.java Wed Jan 16 09:08:24 2013 +0100 @@ -24,6 +24,7 @@ import java.lang.annotation.*; import java.lang.reflect.*; +import java.lang.reflect.Method; import java.util.*; /** @@ -159,4 +160,10 @@ * Returns {@code true} if this method can be inlined. */ boolean canBeInlined(); + + + /** + * Returns the LineNumberTable of this method. + */ + LineNumberTable getLineNumberTable(); } diff -r 36dafe48bc38 -r 42b6e0905881 graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/ResolvedJavaType.java --- a/graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/ResolvedJavaType.java Wed Jan 16 09:05:48 2013 +0100 +++ b/graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/ResolvedJavaType.java Wed Jan 16 09:08:24 2013 +0100 @@ -241,4 +241,9 @@ * @return the field with the given offset, or {@code null} if there is no such field. */ ResolvedJavaField findInstanceFieldWithOffset(long offset); + + /** + * Returns name of source file of this type. + */ + String getSourceFileName(); } diff -r 36dafe48bc38 -r 42b6e0905881 graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/Signature.java --- a/graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/Signature.java Wed Jan 16 09:05:48 2013 +0100 +++ b/graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/Signature.java Wed Jan 16 09:08:24 2013 +0100 @@ -24,14 +24,14 @@ /** * Represents a method signature provided by the runtime. - * - * @see Method Descriptors + * + * @see Method Descriptors */ public interface Signature { /** * Returns the number of parameters in this signature, adding 1 for a receiver if requested. - * + * * @param receiver true if 1 is to be added to the result for a receiver * @return the number of parameters; + 1 iff {@code receiver == true} */ @@ -40,7 +40,7 @@ /** * Gets the parameter type at the specified position. This method returns a {@linkplain ResolvedJavaType resolved} * type if possible but without triggering any class loading or resolution. - * + * * @param index the index into the parameters, with {@code 0} indicating the first parameter * @param accessingClass the context of the type lookup. If accessing class is provided, its class loader is used to * retrieve an existing resolved type. This value can be {@code null} if the caller does not care for a @@ -52,7 +52,7 @@ /** * Gets the parameter kind at the specified position. This is the same as calling {@link #getParameterType}. * {@link JavaType#getKind getKind}. - * + * * @param index the index into the parameters, with {@code 0} indicating the first parameter * @return the kind of the parameter at the specified position */ @@ -61,7 +61,7 @@ /** * Gets the return type of this signature. This method will return a {@linkplain ResolvedJavaType resolved} type if * possible but without triggering any class loading or resolution. - * + * * @param accessingClass the context of the type lookup. If accessing class is provided, its class loader is used to * retrieve an existing resolved type. This value can be {@code null} if the caller does not care for a * resolved type. @@ -77,10 +77,21 @@ /** * Gets the size, in Java slots, of the parameters to this signature. - * + * * @param withReceiver {@code true} if to add a slot for a receiver object; {@code false} not to include the * receiver * @return the size of the parameters in slots */ int getParameterSlots(boolean withReceiver); + + /** + * Gets the method + * descriptor corresponding to this signature. + * For example: + * + *
(ILjava/lang/String;D)V
. + * + * @return the signature as a string + */ + String getMethodDescriptor(); } diff -r 36dafe48bc38 -r 42b6e0905881 graal/com.oracle.graal.asm.amd64/src/com/oracle/graal/asm/amd64/AMD64AsmOptions.java diff -r 36dafe48bc38 -r 42b6e0905881 graal/com.oracle.graal.asm.amd64/src/com/oracle/graal/asm/amd64/AMD64Assembler.java diff -r 36dafe48bc38 -r 42b6e0905881 graal/com.oracle.graal.asm/src/com/oracle/graal/asm/AbstractAssembler.java diff -r 36dafe48bc38 -r 42b6e0905881 graal/com.oracle.graal.compiler.amd64/src/com/oracle/graal/compiler/amd64/AMD64LIRGenerator.java --- a/graal/com.oracle.graal.compiler.amd64/src/com/oracle/graal/compiler/amd64/AMD64LIRGenerator.java Wed Jan 16 09:05:48 2013 +0100 +++ b/graal/com.oracle.graal.compiler.amd64/src/com/oracle/graal/compiler/amd64/AMD64LIRGenerator.java Wed Jan 16 09:08:24 2013 +0100 @@ -40,7 +40,6 @@ import com.oracle.graal.graph.*; import com.oracle.graal.lir.*; import com.oracle.graal.lir.StandardOp.JumpOp; -import com.oracle.graal.lir.StandardOp.LabelOp; import com.oracle.graal.lir.amd64.AMD64Arithmetic.DivOp; import com.oracle.graal.lir.amd64.AMD64Arithmetic.Op1Reg; import com.oracle.graal.lir.amd64.AMD64Arithmetic.Op1Stack; @@ -221,11 +220,6 @@ } @Override - public void emitLabel(Label label, boolean align) { - append(new LabelOp(label, align)); - } - - @Override public void emitJump(LabelRef label, LIRFrameState info) { append(new JumpOp(label, info)); } @@ -346,7 +340,49 @@ } @Override - public Variable emitDiv(Value a, Value b) { + protected boolean peephole(ValueNode valueNode) { + if ((valueNode instanceof IntegerDivNode) || (valueNode instanceof IntegerRemNode)) { + FixedBinaryNode divRem = (FixedBinaryNode) valueNode; + FixedNode node = divRem.next(); + while (node instanceof FixedWithNextNode) { + FixedWithNextNode fixedWithNextNode = (FixedWithNextNode) node; + if (((fixedWithNextNode instanceof IntegerDivNode) || (fixedWithNextNode instanceof IntegerRemNode)) && fixedWithNextNode.getClass() != divRem.getClass()) { + FixedBinaryNode otherDivRem = (FixedBinaryNode) fixedWithNextNode; + if (otherDivRem.x() == divRem.x() && otherDivRem.y() == divRem.y() && operand(otherDivRem) == null) { + Value[] results = emitIntegerDivRem(operand(divRem.x()), operand(divRem.y())); + if (divRem instanceof IntegerDivNode) { + setResult(divRem, results[0]); + setResult(otherDivRem, results[1]); + } else { + setResult(divRem, results[1]); + setResult(otherDivRem, results[0]); + } + return true; + } + } + node = fixedWithNextNode.next(); + } + } + return false; + } + + public Value[] emitIntegerDivRem(Value a, Value b) { + switch(a.getKind()) { + case Int: + emitMove(a, RAX_I); + append(new DivRemOp(IDIVREM, RAX_I, load(b), state())); + return new Value[]{emitMove(RAX_I), emitMove(RDX_I)}; + case Long: + emitMove(a, RAX_L); + append(new DivRemOp(LDIVREM, RAX_L, load(b), state())); + return new Value[]{emitMove(RAX_L), emitMove(RDX_L)}; + default: + throw GraalInternalError.shouldNotReachHere(); + } + } + + @Override + public Value emitDiv(Value a, Value b) { switch(a.getKind()) { case Int: emitMove(a, RAX_I); diff -r 36dafe48bc38 -r 42b6e0905881 graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/GraalCompilerTest.java --- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/GraalCompilerTest.java Wed Jan 16 09:05:48 2013 +0100 +++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/GraalCompilerTest.java Wed Jan 16 09:08:24 2013 +0100 @@ -42,6 +42,7 @@ import com.oracle.graal.phases.*; import com.oracle.graal.phases.PhasePlan.PhasePosition; import com.oracle.graal.phases.schedule.*; +import com.oracle.graal.printer.*; /** * Base class for Graal compiler unit tests. @@ -68,7 +69,7 @@ protected final GraalCompiler graalCompiler; public GraalCompilerTest() { - Debug.enable(); + DebugEnvironment.initialize(System.out); this.runtime = Graal.getRequiredCapability(GraalCodeCacheProvider.class); this.graalCompiler = Graal.getRequiredCapability(GraalCompiler.class); } diff -r 36dafe48bc38 -r 42b6e0905881 graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/IfBoxingEliminationTest.java --- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/IfBoxingEliminationTest.java Wed Jan 16 09:05:48 2013 +0100 +++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/IfBoxingEliminationTest.java Wed Jan 16 09:08:24 2013 +0100 @@ -97,6 +97,7 @@ Debug.dump(graph, "Graph"); new ExpandBoxingNodesPhase(pool).apply(graph); new CanonicalizerPhase(null, runtime(), assumptions).apply(graph); + new CanonicalizerPhase(null, runtime(), assumptions).apply(graph); new DeadCodeEliminationPhase().apply(graph); StructuredGraph referenceGraph = parse(REFERENCE_SNIPPET); new CanonicalizerPhase(null, runtime(), assumptions).apply(referenceGraph); diff -r 36dafe48bc38 -r 42b6e0905881 graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/DebugFilter.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/DebugFilter.java Wed Jan 16 09:08:24 2013 +0100 @@ -0,0 +1,159 @@ +/* + * 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; + +import java.util.*; +import java.util.regex.*; + +import com.oracle.graal.debug.*; +import com.oracle.graal.debug.internal.*; +import com.oracle.graal.phases.*; + +/** + * Implements the filter specified by the {@link GraalOptions#Dump}, + * {@link GraalOptions#Log}, {@link GraalOptions#Meter} and {@link GraalOptions#Time} + * options. + *

+ * These options enable the associated debug facility if their filter + * matches the {@linkplain DebugScope#getQualifiedName() name} of the + * {@linkplain Debug#currentScope() current scope}. + *

+ * A filter is a list of comma-separated terms. Each term is interpreted + * as a glob pattern if it contains a "*" or "?" character. Otherwise, it is + * interpreted as a substring. If a term starts with "~", then it is an + * positive term. An input is matched by a filter if any of its positive + * terms match the input (or it has no positive terms) AND none of its + * negative terms match the input (or it has no negative terms). + *

+ * Examples of filters include: + *

+ *

    + *
  • ""
    + * Matches any scope.
  • + *
  • "*"
    + * Matches any scope.
  • + *
  • "CodeGen,CodeInstall"
    + * Matches a scope whose name contains "CodeGen" or "CodeInstall".
  • + *
  • "Code*"
    + * Matches a scope whose name starts with "Code".
  • + *
  • "Code,~Dead"
    + * Matches a scope whose name contains "Code" but does not contain "Dead".
  • + *
+ */ +class DebugFilter { + + public static DebugFilter parse(String spec) { + if (spec == null) { + return null; + } + return new DebugFilter(spec.split(",")); + } + + final Term[] positive; + final Term[] negative; + + DebugFilter(String[] terms) { + List pos = new ArrayList<>(terms.length); + List neg = new ArrayList<>(terms.length); + for (int i = 0; i < terms.length; i++) { + String t = terms[i]; + if (t.startsWith("~")) { + neg.add(new Term(t.substring(1))); + } else { + pos.add(new Term(t)); + } + } + this.positive = pos.isEmpty() ? null : pos.toArray(new Term[pos.size()]); + this.negative = neg.isEmpty() ? null : neg.toArray(new Term[neg.size()]); + } + + /** + * Determines if a given input is matched by this filter. + */ + public boolean matches(String input) { + boolean match = true; + if (positive != null) { + match = false; + for (Term t : positive) { + if (t.matches(input)) { + match = true; + break; + } + } + } + if (match && negative != null) { + for (Term t : negative) { + if (t.matches(input)) { + match = false; + break; + } + } + } +// if (match) { +// System.out.println(this + " matches " + input); +// } + return match; + } + + @Override + public String toString() { + StringBuilder buf = new StringBuilder("DebugFilter["); + String sep = ""; + if (positive != null) { + buf.append(sep).append("pos=").append(Arrays.toString(positive)); + sep = ", "; + } + if (negative != null) { + buf.append(sep).append("neg=").append(Arrays.toString(negative)); + sep = ", "; + } + return buf.append("]").toString(); + } + + static class Term { + + final Pattern pattern; + + public Term(String filter) { + if (filter.isEmpty()) { + this.pattern = null; + } else if (filter.contains("*") || filter.contains("?")) { + this.pattern = Pattern.compile(MethodFilter.createGlobString(filter)); + } else { + this.pattern = Pattern.compile(".*" + MethodFilter.createGlobString(filter) + ".*"); + } + } + + /** + * Determines if a given input is matched by this filter. + */ + public boolean matches(String input) { + return pattern == null || pattern.matcher(input).matches(); + } + + @Override + public String toString() { + return pattern == null ? ".*" : pattern.toString(); + } + } +} diff -r 36dafe48bc38 -r 42b6e0905881 graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/GraalCompiler.java --- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/GraalCompiler.java Wed Jan 16 09:05:48 2013 +0100 +++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/GraalCompiler.java Wed Jan 16 09:08:24 2013 +0100 @@ -168,7 +168,7 @@ if (GraalOptions.OptFloatingReads) { int mark = graph.getMark(); new FloatingReadPhase().apply(graph); - new CanonicalizerPhase(target, runtime, assumptions, mark).apply(graph); + new CanonicalizerPhase(target, runtime, assumptions, mark, null).apply(graph); if (GraalOptions.OptReadElimination) { new ReadEliminationPhase().apply(graph); } @@ -209,6 +209,8 @@ assert startBlock != null; assert startBlock.numberOfPreds() == 0; + new ComputeProbabilityPhase().apply(graph); + return Debug.scope("ComputeLinearScanOrder", new Callable() { @Override @@ -228,6 +230,7 @@ } }); + } public FrameMap emitLIR(final LIR lir, StructuredGraph graph, final ResolvedJavaMethod method) { @@ -238,11 +241,22 @@ public void run() { for (Block b : lir.linearScanOrder()) { - lirGenerator.doBlock(b); + emitBlock(b); } Debug.dump(lir, "After LIR generation"); } + + private void emitBlock(Block b) { + if (lir.lir(b) == null) { + for (Block pred : b.getPredecessors()) { + if (!b.isLoopHeader() || !pred.isLoopEnd()) { + emitBlock(pred); + } + } + lirGenerator.doBlock(b); + } + } }); Debug.scope("Allocator", new Runnable() { diff -r 36dafe48bc38 -r 42b6e0905881 graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/GraalDebugConfig.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/GraalDebugConfig.java Wed Jan 16 09:08:24 2013 +0100 @@ -0,0 +1,186 @@ +/* + * 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; + +import java.io.*; +import java.util.*; + +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.nodes.util.*; +import com.oracle.graal.phases.*; + +public class GraalDebugConfig implements DebugConfig { + + private final DebugFilter logFilter; + private final DebugFilter meterFilter; + private final DebugFilter timerFilter; + private final DebugFilter dumpFilter; + private final MethodFilter[] methodFilter; + private final List dumpHandlers; + private final PrintStream output; + private final Set extraFilters = new HashSet<>(); + + public GraalDebugConfig(String logFilter, String meterFilter, String timerFilter, String dumpFilter, String methodFilter, PrintStream output, List dumpHandlers) { + this.logFilter = DebugFilter.parse(logFilter); + this.meterFilter = DebugFilter.parse(meterFilter); + this.timerFilter = DebugFilter.parse(timerFilter); + this.dumpFilter = DebugFilter.parse(dumpFilter); + if (methodFilter == null || methodFilter.isEmpty()) { + this.methodFilter = null; + } else { + String[] filters = methodFilter.split(","); + this.methodFilter = new MethodFilter[filters.length]; + for (int i = 0; i < filters.length; i++) { + this.methodFilter[i] = new MethodFilter(filters[i]); + } + } + + // Report the filters that have been configured so the user can verify it's what they expect + if (logFilter != null || meterFilter != null || timerFilter != null || dumpFilter != null || methodFilter != null) { + TTY.println(Thread.currentThread().getName() + ": " + toString()); + } + this.dumpHandlers = dumpHandlers; + this.output = output; + } + + public boolean isLogEnabled() { + return isEnabled(logFilter); + } + + public boolean isMeterEnabled() { + return isEnabled(meterFilter); + } + + public boolean isDumpEnabled() { + return isEnabled(dumpFilter); + } + + public boolean isTimeEnabled() { + return isEnabled(timerFilter); + } + + public PrintStream output() { + return output; + } + + private boolean isEnabled(DebugFilter filter) { + return checkDebugFilter(Debug.currentScope(), filter) && checkMethodFilter(); + } + + private static boolean checkDebugFilter(String currentScope, DebugFilter filter) { + return filter != null && filter.matches(currentScope); + } + + private boolean checkMethodFilter() { + if (methodFilter == null && extraFilters.isEmpty()) { + return true; + } else { + for (Object o : Debug.context()) { + if (extraFilters.contains(o)) { + return true; + } else if (methodFilter != null) { + if (o instanceof JavaMethod) { + for (MethodFilter filter : methodFilter) { + if (filter.matches((JavaMethod) o)) { + return true; + } + } + } + } + } + return false; + } + } + + @Override + public String toString() { + StringBuilder sb = new StringBuilder(); + sb.append("Debug config:"); + add(sb, "Log", logFilter); + add(sb, "Meter", meterFilter); + add(sb, "Time", timerFilter); + add(sb, "Dump", dumpFilter); + add(sb, "MethodFilter", methodFilter); + return sb.toString(); + } + + private static void add(StringBuilder sb, String name, Object filter) { + if (filter != null) { + sb.append(' '); + sb.append(name); + sb.append('='); + if (filter instanceof Object[]) { + sb.append(Arrays.toString((Object[]) filter)); + } else { + sb.append(String.valueOf(filter)); + } + } + } + + @Override + public RuntimeException interceptException(Throwable e) { + if (e instanceof BailoutException) { + return null; + } + Debug.setConfig(Debug.fixedConfig(true, true, false, false, dumpHandlers, output)); + Debug.log(String.format("Exception occurred in scope: %s", Debug.currentScope())); + for (Object o : Debug.context()) { + if (o instanceof Graph) { + Debug.log("Context obj %s", o); + if (GraalOptions.DumpOnError) { + Debug.dump(o, "Exception graph"); + } else { + Debug.log("Use -G:+DumpOnError to enable dumping of graphs on this error"); + } + } else if (o instanceof Node) { + String location = GraphUtil.approxSourceLocation((Node) o); + if (location != null) { + Debug.log("Context obj %s (approx. location: %s)", o, location); + } else { + Debug.log("Context obj %s", o); + } + } else { + Debug.log("Context obj %s", o); + } + } + return null; + } + + @Override + public Collection dumpHandlers() { + return dumpHandlers; + } + + @Override + public void addToContext(Object o) { + extraFilters.add(o); + } + + @Override + public void removeFromContext(Object o) { + extraFilters.remove(o); + } +} diff -r 36dafe48bc38 -r 42b6e0905881 graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/MethodFilter.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/MethodFilter.java Wed Jan 16 09:08:24 2013 +0100 @@ -0,0 +1,151 @@ +/* + * 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; + +import java.util.*; +import java.util.regex.*; + +import com.oracle.graal.api.meta.*; + +/** + * This class implements a method filter that can filter based on class name, method name and parameters. + * The syntax for the source pattern that is passed to the constructor is as follows: + * + *
+ * SourcePattern = [ Class "." ] method [ "(" [ Parameter { ";" Parameter } ] ")" ] .
+ * Parameter = Class | "int" | "long" | "float" | "double" | "short" | "char" | "boolean" .
+ * Class = { package "." } class .
+ * 
+ * + * + * Glob pattern matching (*, ?) is allowed in all parts of the source pattern. Examples for valid filters are: + * + *
    + *
  • visit(Argument;BlockScope)
    + * Matches all methods named "visit", with the first parameter of type "Argument", and the second parameter of type "BlockScope". + * The packages of the parameter types are irrelevant.
  • + *
  • arraycopy(Object;;;;)
    + * Matches all methods named "arraycopy", with the first parameter of type "Object", and four more parameters of any type. + * The packages of the parameter types are irrelevant.
  • + *
  • com.oracle.graal.compiler.graph.PostOrderNodeIterator.*
    + * Matches all methods in the class "com.oracle.graal.compiler.graph.PostOrderNodeIterator".
  • + *
  • *
    + * Matches all methods in all classes
  • + *
  • com.oracle.graal.compiler.graph.*.visit
    + * Matches all methods named "visit" in classes in the package "com.oracle.graal.compiler.graph". + *
+ */ +public class MethodFilter { + + private final Pattern clazz; + private final Pattern methodName; + private final Pattern[] signature; + + public MethodFilter(String sourcePattern) { + String pattern = sourcePattern.trim(); + + // extract parameter part + int pos = pattern.indexOf('('); + if (pos != -1) { + if (pattern.charAt(pattern.length() - 1) != ')') { + throw new IllegalArgumentException("missing ')' at end of method filter pattern: " + pattern); + } + String[] signatureClasses = pattern.substring(pos + 1, pattern.length() - 1).split(";", -1); + signature = new Pattern[signatureClasses.length]; + for (int i = 0; i < signatureClasses.length; i++) { + signature[i] = createClassGlobPattern(signatureClasses[i].trim()); + } + pattern = pattern.substring(0, pos); + } else { + signature = null; + } + + // If there is at least one "." then everything before the last "." is the class name. + // Otherwise, the pattern contains only the method name. + pos = pattern.lastIndexOf('.'); + if (pos != -1) { + clazz = createClassGlobPattern(pattern.substring(0, pos)); + methodName = Pattern.compile(createGlobString(pattern.substring(pos + 1))); + } else { + clazz = null; + methodName = Pattern.compile(createGlobString(pattern)); + } + } + + static String createGlobString(String pattern) { + return Pattern.quote(pattern).replace("?", "\\E.\\Q").replace("*", "\\E.*\\Q"); + } + + private static Pattern createClassGlobPattern(String pattern) { + if (pattern.length() == 0) { + return null; + } else if (pattern.contains(".")) { + return Pattern.compile(createGlobString(pattern)); + } else { + return Pattern.compile("([^\\.]*\\.)*" + createGlobString(pattern)); + } + } + + public boolean matches(JavaMethod o) { + // check method name first, since MetaUtil.toJavaName is expensive + if (methodName != null && !methodName.matcher(o.getName()).matches()) { + return false; + } + if (clazz != null && !clazz.matcher(MetaUtil.toJavaName(o.getDeclaringClass())).matches()) { + return false; + } + if (signature != null) { + Signature sig = o.getSignature(); + if (sig.getParameterCount(false) != signature.length) { + return false; + } + for (int i = 0; i < signature.length; i++) { + JavaType type = sig.getParameterType(i, null); + String javaName = MetaUtil.toJavaName(type); + if (signature[i] != null && !signature[i].matcher(javaName).matches()) { + return false; + } + } + } + return true; + } + + @Override + public String toString() { + StringBuilder buf = new StringBuilder("MethodFilter["); + String sep = ""; + if (clazz != null) { + buf.append(sep).append("clazz=").append(clazz); + sep = ", "; + } + if (methodName != null) { + buf.append(sep).append("methodName=").append(methodName); + sep = ", "; + } + if (signature != null) { + buf.append(sep).append("signature=").append(Arrays.toString(signature)); + sep = ", "; + } + return buf.append("]").toString(); + } +} diff -r 36dafe48bc38 -r 42b6e0905881 graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/gen/LIRGenerator.java --- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/gen/LIRGenerator.java Wed Jan 16 09:05:48 2013 +0100 +++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/gen/LIRGenerator.java Wed Jan 16 09:08:24 2013 +0100 @@ -373,12 +373,20 @@ stateAfter = ((StateSplit) instr).stateAfter(); } if (instr instanceof ValueNode) { - try { - doRoot((ValueNode) instr); - } catch (GraalInternalError e) { - throw e.addContext(instr); - } catch (Throwable e) { - throw new GraalInternalError(e).addContext(instr); + + ValueNode valueNode = (ValueNode) instr; + if (operand(valueNode) == null) { + if (!peephole(valueNode)) { + try { + doRoot((ValueNode) instr); + } catch (GraalInternalError e) { + throw e.addContext(instr); + } catch (Throwable e) { + throw new GraalInternalError(e).addContext(instr); + } + } + } else { + // There can be cases in which the result of an instruction is already set before by other instructions. } } if (stateAfter != null) { @@ -416,6 +424,8 @@ } } + protected abstract boolean peephole(ValueNode valueNode); + private boolean checkStateReady(FrameState state) { FrameState fs = state; while (fs != null) { @@ -670,7 +680,6 @@ } - public abstract void emitLabel(Label label, boolean align); public abstract void emitJump(LabelRef label, LIRFrameState info); public abstract void emitBranch(Value left, Value right, Condition cond, boolean unorderedIsTrue, LabelRef label, LIRFrameState info); public abstract Variable emitCMove(Value leftVal, Value right, Condition cond, boolean unorderedIsTrue, Value trueValue, Value falseValue); diff -r 36dafe48bc38 -r 42b6e0905881 graal/com.oracle.graal.graph.test/src/com/oracle/graal/graph/TestNode.java --- a/graal/com.oracle.graal.graph.test/src/com/oracle/graal/graph/TestNode.java Wed Jan 16 09:05:48 2013 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,37 +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.graph; - - -public class TestNode extends Node implements Node.IterableNodeType { - private String name; - - public TestNode(String name) { - this.name = name; - } - - - public String getName() { - return name; - } -} diff -r 36dafe48bc38 -r 42b6e0905881 graal/com.oracle.graal.graph.test/src/com/oracle/graal/graph/TestNodeInterface.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.graph.test/src/com/oracle/graal/graph/TestNodeInterface.java Wed Jan 16 09:08:24 2013 +0100 @@ -0,0 +1,28 @@ +/* + * 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.graph; + + +public interface TestNodeInterface { + String getName(); +} diff -r 36dafe48bc38 -r 42b6e0905881 graal/com.oracle.graal.graph.test/src/com/oracle/graal/graph/TypedNodeIteratorTest.java --- a/graal/com.oracle.graal.graph.test/src/com/oracle/graal/graph/TypedNodeIteratorTest.java Wed Jan 16 09:05:48 2013 +0100 +++ b/graal/com.oracle.graal.graph.test/src/com/oracle/graal/graph/TypedNodeIteratorTest.java Wed Jan 16 09:08:24 2013 +0100 @@ -31,6 +31,16 @@ public class TypedNodeIteratorTest { + private static class TestNode extends Node implements Node.IterableNodeType, TestNodeInterface { + private final String name; + public TestNode(String name) { + this.name = name; + } + public String getName() { + return name; + } + } + @Test public void singleNodeTest() { Graph graph = new Graph(); @@ -144,9 +154,9 @@ assertEquals(3, z); } - private static String toString(Iterable nodes) { + public static String toString(Iterable nodes) { StringBuilder sb = new StringBuilder(); - for (TestNode tn : nodes) { + for (TestNodeInterface tn : nodes) { sb.append(tn.getName()); } return sb.toString(); diff -r 36dafe48bc38 -r 42b6e0905881 graal/com.oracle.graal.graph.test/src/com/oracle/graal/graph/TypedNodeIteratorTest2.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.graph.test/src/com/oracle/graal/graph/TypedNodeIteratorTest2.java Wed Jan 16 09:08:24 2013 +0100 @@ -0,0 +1,93 @@ +/* + * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.graal.graph; + +import static org.junit.Assert.*; + +import org.junit.*; + + +public class TypedNodeIteratorTest2 { + + private static class NodeA extends Node implements TestNodeInterface { + private final String name; + public NodeA(String name) { + this.name = name; + } + public String getName() { + return name; + } + } + + private static class NodeB extends NodeA implements Node.IterableNodeType { + public NodeB(String name) { + super(name); + } + } + + private static class NodeC extends NodeB { + public NodeC(String name) { + super(name); + } + } + + private static class NodeD extends NodeC { + public NodeD(String name) { + super(name); + } + } + + @Test + public void simpleSubclassTest() { + Graph graph = new Graph(); + graph.add(new NodeB("b")); + graph.add(new NodeD("d")); + + Assert.assertEquals("bd", TypedNodeIteratorTest.toString(graph.getNodes(NodeB.class))); + Assert.assertEquals("d", TypedNodeIteratorTest.toString(graph.getNodes(NodeD.class))); + } + + @Test + public void addingNodeDuringIterationTest() { + Graph graph = new Graph(); + graph.add(new NodeB("b1")); + NodeD d1 = graph.add(new NodeD("d1")); + StringBuilder sb = new StringBuilder(); + for (NodeB tn : graph.getNodes(NodeB.class)) { + if (tn == d1) { + graph.add(new NodeB("b2")); + } + sb.append(tn.getName()); + } + assertEquals("b1d1b2", sb.toString()); + for (NodeB tn : graph.getNodes(NodeB.class)) { + if (tn == d1) { + graph.add(new NodeB("b3")); + } + assertNotNull(tn); + } + assertEquals(4, graph.getNodes(NodeB.class).count()); + assertEquals(1, graph.getNodes(NodeD.class).count()); + } + +} diff -r 36dafe48bc38 -r 42b6e0905881 graal/com.oracle.graal.graph/src/com/oracle/graal/graph/Graph.java --- a/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/Graph.java Wed Jan 16 09:05:48 2013 +0100 +++ b/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/Graph.java Wed Jan 16 09:08:24 2013 +0100 @@ -310,51 +310,99 @@ }; } - private static class TypedNodeIterator implements Iterator { - private Node current; - private final Node start; + private static class PlaceHolderNode extends Node {} + private static final PlaceHolderNode PLACE_HOLDER = new PlaceHolderNode(); + + private class TypedNodeIterator implements Iterator { + private final int[] ids; + private final Node[] current; + + private int currentIdIndex; + private boolean needsForward; + + public TypedNodeIterator(NodeClass clazz) { + ids = clazz.iterableIds(); + currentIdIndex = 0; + current = new Node[ids.length]; + Arrays.fill(current, PLACE_HOLDER); + needsForward = true; + } + + private Node findNext() { + if (needsForward) { + forward(); + } else { + Node c = current(); + Node afterDeleted = skipDeleted(c); + if (afterDeleted == null) { + needsForward = true; + } else if (c != afterDeleted) { + setCurrent(afterDeleted); + } + } + if (needsForward) { + return null; + } + return current(); + } - public TypedNodeIterator(Node start) { - if (start != null && start.isDeleted()) { - this.current = start; - } else { - this.current = null; + private Node skipDeleted(Node node) { + Node n = node; + while (n != null && n.isDeleted()) { + n = n.typeCacheNext; } - this.start = start; + return n; + } + + private void forward() { + needsForward = false; + int startIdx = currentIdIndex; + while (true) { + Node next; + if (current() == PLACE_HOLDER) { + next = getStartNode(ids[currentIdIndex]); + } else { + next = current().typeCacheNext; + } + next = skipDeleted(next); + if (next == null) { + currentIdIndex++; + if (currentIdIndex >= ids.length) { + currentIdIndex = 0; + } + if (currentIdIndex == startIdx) { + needsForward = true; + return; + } + } else { + setCurrent(next); + break; + } + } + } + + private Node current() { + return current[currentIdIndex]; + } + + private void setCurrent(Node n) { + current[currentIdIndex] = n; } @Override public boolean hasNext() { - if (current != null) { - Node next = current.typeCacheNext; - if (next != null) { - while (next.isDeleted()) { - next = next.typeCacheNext; - if (next == null) { - return false; - } - current.typeCacheNext = next; - } - return true; - } - return false; - } else { - return start != null; - } + return findNext() != null; } @Override @SuppressWarnings("unchecked") public T next() { - if (current == null) { - Node result = start; - current = result; - return (T) result; - } else { - Node result = current.typeCacheNext; - current = result; - return (T) result; + Node result = findNext(); + if (result == null) { + throw new NoSuchElementException(); } + needsForward = true; + return (T) result; } @Override @@ -369,11 +417,11 @@ * @return an {@link Iterable} providing all the matching nodes. */ public NodeIterable getNodes(final Class type) { - final Node start = getStartNode(type); + final NodeClass nodeClass = NodeClass.get(type); return new AbstractNodeIterable() { @Override public Iterator iterator() { - return new TypedNodeIterator<>(start); + return new TypedNodeIterator<>(nodeClass); } }; } @@ -387,10 +435,8 @@ return getNodes(type).iterator().hasNext(); } - private Node getStartNode(final Class type) { - int nodeClassId = NodeClass.get(type).iterableId(); - assert nodeClassId != -1 : type + " is not iterable within graphs (missing \"implements IterableNodeType\"?)"; - Node start = nodeCacheFirst.size() <= nodeClassId ? null : nodeCacheFirst.get(nodeClassId); + private Node getStartNode(int iterableId) { + Node start = nodeCacheFirst.size() <= iterableId ? null : nodeCacheFirst.get(iterableId); return start; } diff -r 36dafe48bc38 -r 42b6e0905881 graal/com.oracle.graal.graph/src/com/oracle/graal/graph/NodeClass.java --- a/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/NodeClass.java Wed Jan 16 09:05:48 2013 +0100 +++ b/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/NodeClass.java Wed Jan 16 09:08:24 2013 +0100 @@ -47,8 +47,7 @@ } } - - public static final int NOT_ITERABLE = -1; + static final int NOT_ITERABLE = -1; private static final Class NODE_CLASS = Node.class; private static final Class INPUT_LIST_CLASS = NodeInputList.class; @@ -66,6 +65,7 @@ private final String shortName; private final String nameTemplate; private final int iterableId; + private int[] iterableIds; public NodeClass(Class clazz) { @@ -110,14 +110,27 @@ this.shortName = newShortName; if (Node.IterableNodeType.class.isAssignableFrom(clazz)) { this.iterableId = nextIterableId++; - // TODO (lstadler) add type hierarchy - based node iteration -// for (NodeClass nodeClass : nodeClasses.values()) { -// if (clazz.isAssignableFrom(nodeClass.clazz)) { -// throw new UnsupportedOperationException("iterable non-final Node classes not supported: " + clazz); -// } -// } + List existingClasses = new LinkedList<>(); + for (FieldIntrospection nodeClass : allClasses.values()) { + if (clazz.isAssignableFrom(nodeClass.clazz)) { + existingClasses.add((NodeClass) nodeClass); + } + if (nodeClass.clazz.isAssignableFrom(clazz) && Node.IterableNodeType.class.isAssignableFrom(nodeClass.clazz)) { + NodeClass superNodeClass = (NodeClass) nodeClass; + superNodeClass.iterableIds = Arrays.copyOf(superNodeClass.iterableIds, superNodeClass.iterableIds.length + 1); + superNodeClass.iterableIds[superNodeClass.iterableIds.length - 1] = this.iterableId; + } + } + int[] ids = new int[existingClasses.size() + 1]; + ids[0] = iterableId; + int i = 1; + for (NodeClass other : existingClasses) { + ids[i++] = other.iterableId; + } + this.iterableIds = ids; } else { this.iterableId = NOT_ITERABLE; + this.iterableIds = null; } } @@ -145,6 +158,10 @@ return shortName; } + public int[] iterableIds() { + return iterableIds; + } + public int iterableId() { return iterableId; } diff -r 36dafe48bc38 -r 42b6e0905881 graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotRegisterConfig.java --- a/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotRegisterConfig.java Wed Jan 16 09:05:48 2013 +0100 +++ b/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotRegisterConfig.java Wed Jan 16 09:08:24 2013 +0100 @@ -62,16 +62,19 @@ return attributesMap; } - private final Register[] generalParameterRegisters; + private final Register[] javaGeneralParameterRegisters; + private final Register[] nativeGeneralParameterRegisters; private final Register[] xmmParameterRegisters = {xmm0, xmm1, xmm2, xmm3, xmm4, xmm5, xmm6, xmm7}; private final CalleeSaveLayout csl; public AMD64HotSpotRegisterConfig(HotSpotVMConfig config, boolean globalStubConfig) { if (config.windowsOs) { - generalParameterRegisters = new Register[] {rdx, r8, r9, rdi, rsi, rcx}; + javaGeneralParameterRegisters = new Register[] {rdx, r8, r9, rdi, rsi, rcx}; + nativeGeneralParameterRegisters = new Register[] {rcx, rdx, r8, r9}; } else { - generalParameterRegisters = new Register[] {rsi, rdx, rcx, r8, r9, rdi}; + javaGeneralParameterRegisters = new Register[] {rsi, rdx, rcx, r8, r9, rdi}; + nativeGeneralParameterRegisters = new Register[] {rdi, rsi, rdx, rcx, r8, r9}; } if (globalStubConfig) { @@ -107,19 +110,19 @@ @Override public CallingConvention getCallingConvention(Type type, JavaType returnType, JavaType[] parameterTypes, TargetDescription target, boolean stackOnly) { if (type == Type.NativeCall) { - throw new UnsupportedOperationException(); + return callingConvention(nativeGeneralParameterRegisters, returnType, parameterTypes, type, target, stackOnly); } - return callingConvention(returnType, parameterTypes, type, target, stackOnly); + return callingConvention(javaGeneralParameterRegisters, returnType, parameterTypes, type, target, stackOnly); } public Register[] getCallingConventionRegisters(Type type, RegisterFlag flag) { if (flag == RegisterFlag.FPU) { return xmmParameterRegisters; } - return generalParameterRegisters; + return type == Type.NativeCall ? nativeGeneralParameterRegisters : javaGeneralParameterRegisters; } - private CallingConvention callingConvention(JavaType returnType, JavaType[] parameterTypes, Type type, TargetDescription target, boolean stackOnly) { + private CallingConvention callingConvention(Register[] generalParameterRegisters, JavaType returnType, JavaType[] parameterTypes, Type type, TargetDescription target, boolean stackOnly) { Value[] locations = new Value[parameterTypes.length]; int currentGeneral = 0; diff -r 36dafe48bc38 -r 42b6e0905881 graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotRuntime.java --- a/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotRuntime.java Wed Jan 16 09:05:48 2013 +0100 +++ b/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotRuntime.java Wed Jan 16 09:08:24 2013 +0100 @@ -25,6 +25,7 @@ import static com.oracle.graal.amd64.AMD64.*; import static com.oracle.graal.compiler.amd64.AMD64DeoptimizationStub.*; import static com.oracle.graal.compiler.amd64.AMD64LIRGenerator.*; +import static com.oracle.graal.hotspot.nodes.IdentityHashCodeStubCall.*; import static com.oracle.graal.hotspot.nodes.MonitorEnterStubCall.*; import static com.oracle.graal.hotspot.nodes.MonitorExitStubCall.*; import static com.oracle.graal.hotspot.nodes.NewArraySlowStubCall.*; @@ -32,10 +33,13 @@ import static com.oracle.graal.hotspot.nodes.NewInstanceSlowStubCall.*; import static com.oracle.graal.hotspot.nodes.NewInstanceStubCall.*; import static com.oracle.graal.hotspot.nodes.NewMultiArrayStubCall.*; +import static com.oracle.graal.hotspot.nodes.ThreadIsInterruptedStubCall.*; import static com.oracle.graal.hotspot.nodes.VMErrorNode.*; import static com.oracle.graal.hotspot.nodes.VerifyOopStubCall.*; -import static com.oracle.graal.hotspot.nodes.IdentityHashCodeStubCall.*; -import static com.oracle.graal.hotspot.nodes.ThreadIsInterruptedStubCall.*; +import static com.oracle.graal.hotspot.snippets.AESCryptSubstitutions.DecryptBlockStubCall.*; +import static com.oracle.graal.hotspot.snippets.AESCryptSubstitutions.EncryptBlockStubCall.*; +import static com.oracle.graal.hotspot.snippets.CipherBlockChainingSubstitutions.DecryptAESCryptStubCall.*; +import static com.oracle.graal.hotspot.snippets.CipherBlockChainingSubstitutions.EncryptAESCryptStubCall.*; import static com.oracle.graal.lir.amd64.AMD64Call.*; import com.oracle.graal.api.code.*; @@ -66,26 +70,26 @@ addRuntimeCall(ARITHMETIC_FREM, config.arithmeticFremStub, /* temps */ null, /* ret */ ret(Kind.Float), - /* arg0: a */ arg(0, Kind.Float), - /* arg1: b */ arg(1, Kind.Float)); + /* arg0: a */ jarg(0, Kind.Float), + /* arg1: b */ jarg(1, Kind.Float)); addRuntimeCall(ARITHMETIC_DREM, config.arithmeticDremStub, /* temps */ null, /* ret */ ret(Kind.Double), - /* arg0: a */ arg(0, Kind.Double), - /* arg1: b */ arg(1, Kind.Double)); + /* arg0: a */ jarg(0, Kind.Double), + /* arg1: b */ jarg(1, Kind.Double)); addRuntimeCall(MONITORENTER, config.monitorEnterStub, /* temps */ null, /* ret */ ret(Kind.Void), - /* arg0: object */ arg(0, Kind.Object), - /* arg1: lock */ arg(1, word)); + /* arg0: object */ jarg(0, Kind.Object), + /* arg1: lock */ jarg(1, word)); addRuntimeCall(MONITOREXIT, config.monitorExitStub, /* temps */ null, /* ret */ ret(Kind.Void), - /* arg0: object */ arg(0, Kind.Object), - /* arg1: lock */ arg(1, word)); + /* arg0: object */ jarg(0, Kind.Object), + /* arg1: lock */ jarg(1, word)); addRuntimeCall(NEW_ARRAY, 0L, /* temps */ null, @@ -124,20 +128,52 @@ addRuntimeCall(VM_ERROR, config.vmErrorStub, /* temps */ null, /* ret */ ret(Kind.Void), - /* arg0: where */ arg(0, Kind.Object), - /* arg1: format */ arg(1, Kind.Object), - /* arg2: value */ arg(2, Kind.Long)); + /* arg0: where */ jarg(0, Kind.Object), + /* arg1: format */ jarg(1, Kind.Object), + /* arg2: value */ jarg(2, Kind.Long)); addRuntimeCall(IDENTITY_HASHCODE, config.identityHashCodeStub, /* temps */ null, /* ret */ rax.asValue(Kind.Int), - /* arg0: obj */ arg(0, Kind.Object)); + /* arg0: obj */ jarg(0, Kind.Object)); addRuntimeCall(THREAD_IS_INTERRUPTED, config.threadIsInterruptedStub, /* temps */ null, /* ret */ rax.asValue(Kind.Int), - /* arg0: thread */ arg(0, Kind.Object), - /* arg1: clearInterrupted */ arg(1, Kind.Boolean)); + /* arg0: thread */ jarg(0, Kind.Object), + /* arg1: clearInterrupted */ jarg(1, Kind.Boolean)); + + addRuntimeCall(ENCRYPT_BLOCK, config.aescryptEncryptBlockStub, + /* temps */ null, + /* ret */ ret(Kind.Void), + /* arg0: in */ carg(0, word), + /* arg1: out */ carg(1, word), + /* arg2: key */ carg(2, word)); + + addRuntimeCall(DECRYPT_BLOCK, config.aescryptDecryptBlockStub, + /* temps */ null, + /* ret */ ret(Kind.Void), + /* arg0: in */ carg(0, word), + /* arg1: out */ carg(1, word), + /* arg2: key */ carg(2, word)); + + addRuntimeCall(ENCRYPT, config.cipherBlockChainingEncryptAESCryptStub, + /* temps */ null, + /* ret */ ret(Kind.Void), + /* arg0: in */ carg(0, word), + /* arg1: out */ carg(1, word), + /* arg2: key */ carg(2, word), + /* arg3: r */ carg(3, word), + /* arg4: inLength */ carg(4, Kind.Int)); + + addRuntimeCall(DECRYPT, config.cipherBlockChainingDecryptAESCryptStub, + /* temps */ null, + /* ret */ ret(Kind.Void), + /* arg0: in */ carg(0, word), + /* arg1: out */ carg(1, word), + /* arg2: key */ carg(2, word), + /* arg3: r */ carg(3, word), + /* arg4: inLength */ carg(4, Kind.Int)); } @Override diff -r 36dafe48bc38 -r 42b6e0905881 graal/com.oracle.graal.hotspot.test/src/com/oracle/graal/hotspot/ArrayCopyIntrinsificationTest.java diff -r 36dafe48bc38 -r 42b6e0905881 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/CompilationTask.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/CompilationTask.java Wed Jan 16 09:05:48 2013 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/CompilationTask.java Wed Jan 16 09:08:24 2013 +0100 @@ -22,11 +22,14 @@ */ package com.oracle.graal.hotspot; +import static com.oracle.graal.nodes.StructuredGraph.*; + import java.util.concurrent.*; 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.meta.*; import com.oracle.graal.nodes.*; import com.oracle.graal.phases.*; @@ -127,7 +130,14 @@ @Override public CompilationResult call() throws Exception { graalRuntime.evictDeoptedGraphs(); - StructuredGraph graph = new StructuredGraph(method, entryBCI); + StructuredGraph graph = (StructuredGraph) method.getCompilerStorage().get(Graph.class); + if (graph == null || entryBCI != INVOCATION_ENTRY_BCI) { + graph = new StructuredGraph(method, entryBCI); + } else { + // Compiling an intrinsic graph - must clone the graph + graph = graph.copy(); + //System.out.println("compiling intrinsic " + method); + } return graalRuntime.getCompiler().compileMethod(method, graph, graalRuntime.getCache(), plan, optimisticOpts); } }); @@ -183,4 +193,9 @@ return id < o.id ? -1 : (id > o.id ? 1 : 0); } + @Override + public String toString() { + return "Compilation[id=" + id + ", prio=" + priority + " " + MetaUtil.format("%H.%n(%p)", method) + + (entryBCI == StructuredGraph.INVOCATION_ENTRY_BCI ? "" : "@" + entryBCI) + "]"; + } } diff -r 36dafe48bc38 -r 42b6e0905881 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/CompilerThread.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/CompilerThread.java Wed Jan 16 09:05:48 2013 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/CompilerThread.java Wed Jan 16 09:08:24 2013 +0100 @@ -25,8 +25,10 @@ import java.io.*; import java.util.concurrent.*; +import com.oracle.graal.compiler.*; import com.oracle.graal.debug.*; import com.oracle.graal.phases.*; +import com.oracle.graal.printer.*; public final class CompilerThread extends Thread { @@ -56,12 +58,10 @@ @Override public void run() { - HotSpotDebugConfig hotspotDebugConfig = null; + GraalDebugConfig hotspotDebugConfig = null; if (GraalOptions.Debug) { - Debug.enable(); PrintStream log = HotSpotGraalRuntime.getInstance().getVMToCompiler().log(); - hotspotDebugConfig = new HotSpotDebugConfig(GraalOptions.Log, GraalOptions.Meter, GraalOptions.Time, GraalOptions.Dump, GraalOptions.MethodFilter, log); - Debug.setConfig(hotspotDebugConfig); + DebugEnvironment.initialize(log); } try { super.run(); diff -r 36dafe48bc38 -r 42b6e0905881 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/DebugFilter.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/DebugFilter.java Wed Jan 16 09:05:48 2013 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,161 +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; - -import static com.oracle.graal.hotspot.MethodFilter.*; - -import java.util.*; -import java.util.regex.*; - -import com.oracle.graal.debug.*; -import com.oracle.graal.debug.internal.*; -import com.oracle.graal.phases.*; - -/** - * Implements the filter specified by the {@link GraalOptions#Dump}, - * {@link GraalOptions#Log}, {@link GraalOptions#Meter} and {@link GraalOptions#Time} - * options. - *

- * These options enable the associated debug facility if their filter - * matches the {@linkplain DebugScope#getQualifiedName() name} of the - * {@linkplain Debug#currentScope() current scope}. - *

- * A filter is a list of comma-separated terms. Each term is interpreted - * as a glob pattern if it contains a "*" or "?" character. Otherwise, it is - * interpreted as a substring. If a term starts with "~", then it is an - * positive term. An input is matched by a filter if any of its positive - * terms match the input (or it has no positive terms) AND none of its - * negative terms match the input (or it has no negative terms). - *

- * Examples of filters include: - *

- *

    - *
  • ""
    - * Matches any scope.
  • - *
  • "*"
    - * Matches any scope.
  • - *
  • "CodeGen,CodeInstall"
    - * Matches a scope whose name contains "CodeGen" or "CodeInstall".
  • - *
  • "Code*"
    - * Matches a scope whose name starts with "Code".
  • - *
  • "Code,~Dead"
    - * Matches a scope whose name contains "Code" but does not contain "Dead".
  • - *
- */ -class DebugFilter { - - public static DebugFilter parse(String spec) { - if (spec == null) { - return null; - } - return new DebugFilter(spec.split(",")); - } - - final Term[] positive; - final Term[] negative; - - DebugFilter(String[] terms) { - List pos = new ArrayList<>(terms.length); - List neg = new ArrayList<>(terms.length); - for (int i = 0; i < terms.length; i++) { - String t = terms[i]; - if (t.startsWith("~")) { - neg.add(new Term(t.substring(1))); - } else { - pos.add(new Term(t)); - } - } - this.positive = pos.isEmpty() ? null : pos.toArray(new Term[pos.size()]); - this.negative = neg.isEmpty() ? null : neg.toArray(new Term[neg.size()]); - } - - /** - * Determines if a given input is matched by this filter. - */ - public boolean matches(String input) { - boolean match = true; - if (positive != null) { - match = false; - for (Term t : positive) { - if (t.matches(input)) { - match = true; - break; - } - } - } - if (match && negative != null) { - for (Term t : negative) { - if (t.matches(input)) { - match = false; - break; - } - } - } -// if (match) { -// System.out.println(this + " matches " + input); -// } - return match; - } - - @Override - public String toString() { - StringBuilder buf = new StringBuilder("DebugFilter["); - String sep = ""; - if (positive != null) { - buf.append(sep).append("pos=").append(Arrays.toString(positive)); - sep = ", "; - } - if (negative != null) { - buf.append(sep).append("neg=").append(Arrays.toString(negative)); - sep = ", "; - } - return buf.append("]").toString(); - } - - static class Term { - - final Pattern pattern; - - public Term(String filter) { - if (filter.isEmpty()) { - this.pattern = null; - } else if (filter.contains("*") || filter.contains("?")) { - this.pattern = Pattern.compile(createGlobString(filter)); - } else { - this.pattern = Pattern.compile(".*" + createGlobString(filter) + ".*"); - } - } - - /** - * Determines if a given input is matched by this filter. - */ - public boolean matches(String input) { - return pattern == null || pattern.matcher(input).matches(); - } - - @Override - public String toString() { - return pattern == null ? ".*" : pattern.toString(); - } - } -} diff -r 36dafe48bc38 -r 42b6e0905881 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotDebugConfig.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotDebugConfig.java Wed Jan 16 09:05:48 2013 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,193 +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; - -import java.io.*; -import java.util.*; - -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.nodes.util.*; -import com.oracle.graal.phases.*; -import com.oracle.graal.printer.*; - -public class HotSpotDebugConfig implements DebugConfig { - - private final DebugFilter logFilter; - private final DebugFilter meterFilter; - private final DebugFilter timerFilter; - private final DebugFilter dumpFilter; - private final MethodFilter[] methodFilter; - private final List dumpHandlers = new ArrayList<>(); - private final PrintStream output; - private final Set extraFilters = new HashSet<>(); - - public HotSpotDebugConfig(String logFilter, String meterFilter, String timerFilter, String dumpFilter, String methodFilter, PrintStream output) { - this.logFilter = DebugFilter.parse(logFilter); - this.meterFilter = DebugFilter.parse(meterFilter); - this.timerFilter = DebugFilter.parse(timerFilter); - this.dumpFilter = DebugFilter.parse(dumpFilter); - if (methodFilter == null || methodFilter.isEmpty()) { - this.methodFilter = null; - } else { - String[] filters = methodFilter.split(","); - this.methodFilter = new MethodFilter[filters.length]; - for (int i = 0; i < filters.length; i++) { - this.methodFilter[i] = new MethodFilter(filters[i]); - } - } - - // Report the filters that have been configured so the user can verify it's what they expect - if (logFilter != null || meterFilter != null || timerFilter != null || dumpFilter != null || methodFilter != null) { - TTY.println(Thread.currentThread().getName() + ": " + toString()); - } - dumpHandlers.add(new GraphPrinterDumpHandler()); - if (GraalOptions.PrintCFG) { - if (GraalOptions.PrintBinaryGraphs) { - TTY.println("CFG dumping slows down PrintBinaryGraphs: use -G:-PrintCFG to disable it"); - } - dumpHandlers.add(new CFGPrinterObserver()); - } - this.output = output; - } - - public boolean isLogEnabled() { - return isEnabled(logFilter); - } - - public boolean isMeterEnabled() { - return isEnabled(meterFilter); - } - - public boolean isDumpEnabled() { - return isEnabled(dumpFilter); - } - - public boolean isTimeEnabled() { - return isEnabled(timerFilter); - } - - public PrintStream output() { - return output; - } - - private boolean isEnabled(DebugFilter filter) { - return checkDebugFilter(Debug.currentScope(), filter) && checkMethodFilter(); - } - - private static boolean checkDebugFilter(String currentScope, DebugFilter filter) { - return filter != null && filter.matches(currentScope); - } - - private boolean checkMethodFilter() { - if (methodFilter == null && extraFilters.isEmpty()) { - return true; - } else { - for (Object o : Debug.context()) { - if (extraFilters.contains(o)) { - return true; - } else if (methodFilter != null) { - if (o instanceof JavaMethod) { - for (MethodFilter filter : methodFilter) { - if (filter.matches((JavaMethod) o)) { - return true; - } - } - } - } - } - return false; - } - } - - @Override - public String toString() { - StringBuilder sb = new StringBuilder(); - sb.append("Debug config:"); - add(sb, "Log", logFilter); - add(sb, "Meter", meterFilter); - add(sb, "Time", timerFilter); - add(sb, "Dump", dumpFilter); - add(sb, "MethodFilter", methodFilter); - return sb.toString(); - } - - private static void add(StringBuilder sb, String name, Object filter) { - if (filter != null) { - sb.append(' '); - sb.append(name); - sb.append('='); - if (filter instanceof Object[]) { - sb.append(Arrays.toString((Object[]) filter)); - } else { - sb.append(String.valueOf(filter)); - } - } - } - - @Override - public RuntimeException interceptException(Throwable e) { - if (e instanceof BailoutException) { - return null; - } - Debug.setConfig(Debug.fixedConfig(true, true, false, false, dumpHandlers, output)); - Debug.log(String.format("Exception occurred in scope: %s", Debug.currentScope())); - for (Object o : Debug.context()) { - if (o instanceof Graph) { - Debug.log("Context obj %s", o); - if (GraalOptions.DumpOnError) { - Debug.dump(o, "Exception graph"); - } else { - Debug.log("Use -G:+DumpOnError to enable dumping of graphs on this error"); - } - } else if (o instanceof Node) { - String location = GraphUtil.approxSourceLocation((Node) o); - if (location != null) { - Debug.log("Context obj %s (approx. location: %s)", o, location); - } else { - Debug.log("Context obj %s", o); - } - } else { - Debug.log("Context obj %s", o); - } - } - return null; - } - - @Override - public Collection dumpHandlers() { - return dumpHandlers; - } - - @Override - public void addToContext(Object o) { - extraFilters.add(o); - } - - @Override - public void removeFromContext(Object o) { - extraFilters.remove(o); - } -} diff -r 36dafe48bc38 -r 42b6e0905881 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotSnippetInstaller.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotSnippetInstaller.java Wed Jan 16 09:08:24 2013 +0100 @@ -0,0 +1,63 @@ +/* + * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.graal.hotspot; + +import java.lang.reflect.*; + +import com.oracle.graal.api.code.*; +import com.oracle.graal.hotspot.meta.*; +import com.oracle.graal.hotspot.snippets.*; +import com.oracle.graal.snippets.*; + +/** + * Filters certain intrinsifications based on whether there is underlying hardware support for them. + */ +public class HotSpotSnippetInstaller extends SnippetInstaller { + + private final HotSpotVMConfig config; + + public HotSpotSnippetInstaller(HotSpotRuntime runtime, Assumptions assumptions, TargetDescription target) { + super(runtime, assumptions, target); + this.config = runtime.config; + } + + @Override + protected void installSubstitution(Method originalMethod, Method substituteMethod) { + if (substituteMethod.getDeclaringClass() == IntegerSubstitutions.class || substituteMethod.getDeclaringClass() == LongSubstitutions.class) { + if (substituteMethod.getName().equals("bitCount")) { + if (!config.usePopCountInstruction) { + return; + } + } + } else if (substituteMethod.getDeclaringClass() == AESCryptSubstitutions.class || substituteMethod.getDeclaringClass() == CipherBlockChainingSubstitutions.class) { + if (!config.useAESIntrinsics) { + return; + } + assert config.aescryptEncryptBlockStub != 0L; + assert config.aescryptDecryptBlockStub != 0L; + assert config.cipherBlockChainingEncryptAESCryptStub != 0L; + assert config.cipherBlockChainingDecryptAESCryptStub != 0L; + } + super.installSubstitution(originalMethod, substituteMethod); + } +} diff -r 36dafe48bc38 -r 42b6e0905881 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotVMConfig.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotVMConfig.java Wed Jan 16 09:05:48 2013 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotVMConfig.java Wed Jan 16 09:08:24 2013 +0100 @@ -40,6 +40,8 @@ public boolean useFastLocking; public boolean useTLAB; public boolean useBiasedLocking; + public boolean usePopCountInstruction; + public boolean useAESIntrinsics; // offsets, ... public int vmPageSize; @@ -334,6 +336,10 @@ public int deoptReasonNone; public long threadIsInterruptedStub; public long identityHashCodeStub; + public long aescryptEncryptBlockStub; + public long aescryptDecryptBlockStub; + public long cipherBlockChainingEncryptAESCryptStub; + public long cipherBlockChainingDecryptAESCryptStub; public int deoptReasonNullCheck; public int deoptReasonRangeCheck; diff -r 36dafe48bc38 -r 42b6e0905881 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/MethodFilter.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/MethodFilter.java Wed Jan 16 09:05:48 2013 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,151 +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; - -import java.util.*; -import java.util.regex.*; - -import com.oracle.graal.api.meta.*; - -/** - * This class implements a method filter that can filter based on class name, method name and parameters. - * The syntax for the source pattern that is passed to the constructor is as follows: - * - *
- * SourcePattern = [ Class "." ] method [ "(" [ Parameter { ";" Parameter } ] ")" ] .
- * Parameter = Class | "int" | "long" | "float" | "double" | "short" | "char" | "boolean" .
- * Class = { package "." } class .
- * 
- * - * - * Glob pattern matching (*, ?) is allowed in all parts of the source pattern. Examples for valid filters are: - * - *
    - *
  • visit(Argument;BlockScope)
    - * Matches all methods named "visit", with the first parameter of type "Argument", and the second parameter of type "BlockScope". - * The packages of the parameter types are irrelevant.
  • - *
  • arraycopy(Object;;;;)
    - * Matches all methods named "arraycopy", with the first parameter of type "Object", and four more parameters of any type. - * The packages of the parameter types are irrelevant.
  • - *
  • com.oracle.graal.compiler.graph.PostOrderNodeIterator.*
    - * Matches all methods in the class "com.oracle.graal.compiler.graph.PostOrderNodeIterator".
  • - *
  • *
    - * Matches all methods in all classes
  • - *
  • com.oracle.graal.compiler.graph.*.visit
    - * Matches all methods named "visit" in classes in the package "com.oracle.graal.compiler.graph". - *
- */ -public class MethodFilter { - - private final Pattern clazz; - private final Pattern methodName; - private final Pattern[] signature; - - public MethodFilter(String sourcePattern) { - String pattern = sourcePattern.trim(); - - // extract parameter part - int pos = pattern.indexOf('('); - if (pos != -1) { - if (pattern.charAt(pattern.length() - 1) != ')') { - throw new IllegalArgumentException("missing ')' at end of method filter pattern: " + pattern); - } - String[] signatureClasses = pattern.substring(pos + 1, pattern.length() - 1).split(";", -1); - signature = new Pattern[signatureClasses.length]; - for (int i = 0; i < signatureClasses.length; i++) { - signature[i] = createClassGlobPattern(signatureClasses[i].trim()); - } - pattern = pattern.substring(0, pos); - } else { - signature = null; - } - - // If there is at least one "." then everything before the last "." is the class name. - // Otherwise, the pattern contains only the method name. - pos = pattern.lastIndexOf('.'); - if (pos != -1) { - clazz = createClassGlobPattern(pattern.substring(0, pos)); - methodName = Pattern.compile(createGlobString(pattern.substring(pos + 1))); - } else { - clazz = null; - methodName = Pattern.compile(createGlobString(pattern)); - } - } - - static String createGlobString(String pattern) { - return Pattern.quote(pattern).replace("?", "\\E.\\Q").replace("*", "\\E.*\\Q"); - } - - private static Pattern createClassGlobPattern(String pattern) { - if (pattern.length() == 0) { - return null; - } else if (pattern.contains(".")) { - return Pattern.compile(createGlobString(pattern)); - } else { - return Pattern.compile("([^\\.]*\\.)*" + createGlobString(pattern)); - } - } - - public boolean matches(JavaMethod o) { - // check method name first, since MetaUtil.toJavaName is expensive - if (methodName != null && !methodName.matcher(o.getName()).matches()) { - return false; - } - if (clazz != null && !clazz.matcher(MetaUtil.toJavaName(o.getDeclaringClass())).matches()) { - return false; - } - if (signature != null) { - Signature sig = o.getSignature(); - if (sig.getParameterCount(false) != signature.length) { - return false; - } - for (int i = 0; i < signature.length; i++) { - JavaType type = sig.getParameterType(i, null); - String javaName = MetaUtil.toJavaName(type); - if (signature[i] != null && !signature[i].matcher(javaName).matches()) { - return false; - } - } - } - return true; - } - - @Override - public String toString() { - StringBuilder buf = new StringBuilder("MethodFilter["); - String sep = ""; - if (clazz != null) { - buf.append(sep).append("clazz=").append(clazz); - sep = ", "; - } - if (methodName != null) { - buf.append(sep).append("methodName=").append(methodName); - sep = ", "; - } - if (signature != null) { - buf.append(sep).append("signature=").append(Arrays.toString(signature)); - sep = ", "; - } - return buf.append("]").toString(); - } -} diff -r 36dafe48bc38 -r 42b6e0905881 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/bridge/CompilerToVM.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/bridge/CompilerToVM.java Wed Jan 16 09:05:48 2013 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/bridge/CompilerToVM.java Wed Jan 16 09:08:24 2013 +0100 @@ -200,4 +200,10 @@ long[] getDeoptedLeafGraphIds(); String decodePC(long pc); + + + long[] getLineNumberTable(HotSpotResolvedJavaMethod method); + + + String getFileName(HotSpotResolvedJavaType method); } diff -r 36dafe48bc38 -r 42b6e0905881 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/bridge/CompilerToVMImpl.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/bridge/CompilerToVMImpl.java Wed Jan 16 09:05:48 2013 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/bridge/CompilerToVMImpl.java Wed Jan 16 09:08:24 2013 +0100 @@ -142,4 +142,10 @@ @Override public native String decodePC(long pc); + + @Override + public native long[] getLineNumberTable(HotSpotResolvedJavaMethod method); + + @Override + public native String getFileName(HotSpotResolvedJavaType method); } diff -r 36dafe48bc38 -r 42b6e0905881 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/bridge/VMToCompilerImpl.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/bridge/VMToCompilerImpl.java Wed Jan 16 09:05:48 2013 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/bridge/VMToCompilerImpl.java Wed Jan 16 09:08:24 2013 +0100 @@ -23,7 +23,7 @@ package com.oracle.graal.hotspot.bridge; -import static com.oracle.graal.graph.FieldIntrospection.*; +import static com.oracle.graal.graph.UnsafeAccess.*; import java.io.*; import java.lang.reflect.*; @@ -44,6 +44,7 @@ import com.oracle.graal.nodes.*; import com.oracle.graal.phases.*; import com.oracle.graal.phases.PhasePlan.PhasePosition; +import com.oracle.graal.printer.*; import com.oracle.graal.snippets.*; /** @@ -125,9 +126,11 @@ if (GraalOptions.Debug) { Debug.enable(); - HotSpotDebugConfig hotspotDebugConfig = new HotSpotDebugConfig(GraalOptions.Log, GraalOptions.Meter, GraalOptions.Time, GraalOptions.Dump, GraalOptions.MethodFilter, log); - Debug.setConfig(hotspotDebugConfig); + if (GraalOptions.DebugSnippets) { + DebugEnvironment.initialize(log); + } } + // Install intrinsics. GraalCompiler compiler = graalRuntime.getCompiler(); final HotSpotRuntime runtime = (HotSpotRuntime) compiler.runtime; @@ -139,7 +142,7 @@ // Snippets cannot have speculative optimizations since they have to be valid for the entire run of the VM. Assumptions assumptions = new Assumptions(false); VMToCompilerImpl.this.intrinsifyArrayCopy = new IntrinsifyArrayCopyPhase(runtime, assumptions); - SnippetInstaller installer = new SnippetInstaller(runtime, assumptions, runtime.getGraalRuntime().getTarget()); + SnippetInstaller installer = new HotSpotSnippetInstaller(runtime, assumptions, runtime.getGraalRuntime().getTarget()); GraalIntrinsics.installIntrinsics(installer); runtime.installSnippets(installer, assumptions); } diff -r 36dafe48bc38 -r 42b6e0905881 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/debug/LineNumberTableImpl.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/debug/LineNumberTableImpl.java Wed Jan 16 09:08:24 2013 +0100 @@ -0,0 +1,56 @@ +/* + * 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.debug; + +import com.oracle.graal.api.meta.*; + + +public class LineNumberTableImpl implements LineNumberTable { + private final int[] lineNumbers; + private final int[] bci; + + public LineNumberTableImpl(int[] lineNumbers, int[] bci) { + this.lineNumbers = lineNumbers; + this.bci = bci; + } + + @Override + public int[] getLineNumberEntries() { + return lineNumbers; + } + + @Override + public int[] getBciEntries() { + return bci; + } + + @Override + public int getLineNumber(@SuppressWarnings("hiding") int bci) { + for (int i = 0; i < this.bci.length - 1; i++) { + if (this.bci[i] <= bci && bci < this.bci[i + 1]) { + return lineNumbers[i]; + } + } + return lineNumbers[lineNumbers.length - 1]; + } +} diff -r 36dafe48bc38 -r 42b6e0905881 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotResolvedJavaMethod.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotResolvedJavaMethod.java Wed Jan 16 09:05:48 2013 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotResolvedJavaMethod.java Wed Jan 16 09:08:24 2013 +0100 @@ -34,6 +34,7 @@ import com.oracle.graal.api.meta.ProfilingInfo.ExceptionSeen; import com.oracle.graal.bytecode.*; import com.oracle.graal.hotspot.*; +import com.oracle.graal.hotspot.debug.*; import com.oracle.graal.phases.*; /** @@ -290,6 +291,21 @@ return HotSpotGraalRuntime.getInstance().getCompilerToVM().isMethodCompilable(metaspaceMethod); } + @Override + public LineNumberTable getLineNumberTable() { + long[] values = HotSpotGraalRuntime.getInstance().getCompilerToVM().getLineNumberTable(this); + assert values.length % 2 == 0; + int[] bci = new int[values.length / 2]; + int[] line = new int[values.length / 2]; + + for (int i = 0; i < values.length / 2; i++) { + bci[i] = (int) values[i * 2]; + line[i] = (int) values[i * 2 + 1]; + } + + return new LineNumberTableImpl(line, bci); + } + /** * Returns the offset of this method into the v-table. * If the holder is not initialized, returns -1 @@ -309,4 +325,5 @@ public CompilationTask currentTask() { return currentTask; } + } diff -r 36dafe48bc38 -r 42b6e0905881 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotResolvedJavaType.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotResolvedJavaType.java Wed Jan 16 09:05:48 2013 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotResolvedJavaType.java Wed Jan 16 09:08:24 2013 +0100 @@ -23,6 +23,7 @@ package com.oracle.graal.hotspot.meta; import com.oracle.graal.api.meta.*; +import com.oracle.graal.hotspot.*; public abstract class HotSpotResolvedJavaType extends HotSpotJavaType implements ResolvedJavaType { @@ -33,4 +34,9 @@ } public abstract Class mirror(); + + @Override + public String getSourceFileName() { + return HotSpotGraalRuntime.getInstance().getCompilerToVM().getFileName(this); + } } diff -r 36dafe48bc38 -r 42b6e0905881 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotResolvedObjectType.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotResolvedObjectType.java Wed Jan 16 09:05:48 2013 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotResolvedObjectType.java Wed Jan 16 09:08:24 2013 +0100 @@ -330,7 +330,7 @@ @Override public ResolvedJavaMethod resolveMethod(ResolvedJavaMethod method) { assert method instanceof HotSpotMethod; - return (ResolvedJavaMethod) HotSpotGraalRuntime.getInstance().getCompilerToVM().resolveMethod(this, method.getName(), ((HotSpotSignature) method.getSignature()).asString()); + return (ResolvedJavaMethod) HotSpotGraalRuntime.getInstance().getCompilerToVM().resolveMethod(this, method.getName(), ((HotSpotSignature) method.getSignature()).getMethodDescriptor()); } @Override @@ -446,6 +446,11 @@ } @Override + public String getSourceFileName() { + return HotSpotGraalRuntime.getInstance().getCompilerToVM().getFileName(this); + } + + @Override public T getAnnotation(Class annotationClass) { return javaMirror.getAnnotation(annotationClass); } diff -r 36dafe48bc38 -r 42b6e0905881 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotResolvedPrimitiveType.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotResolvedPrimitiveType.java Wed Jan 16 09:05:48 2013 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotResolvedPrimitiveType.java Wed Jan 16 09:08:24 2013 +0100 @@ -181,7 +181,12 @@ } @Override - public Class mirror() { + public String getSourceFileName() { + throw GraalInternalError.shouldNotReachHere(); + } + + @Override + public Class< ? > mirror() { return javaMirror; } } diff -r 36dafe48bc38 -r 42b6e0905881 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotRuntime.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotRuntime.java Wed Jan 16 09:05:48 2013 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotRuntime.java Wed Jan 16 09:08:24 2013 +0100 @@ -24,15 +24,17 @@ import static com.oracle.graal.api.code.DeoptimizationAction.*; import static com.oracle.graal.api.code.MemoryBarriers.*; +import static com.oracle.graal.api.code.Register.RegisterFlag.*; import static com.oracle.graal.api.meta.DeoptimizationReason.*; import static com.oracle.graal.api.meta.Value.*; import static com.oracle.graal.hotspot.HotSpotGraalRuntime.*; -import static com.oracle.graal.hotspot.snippets.SystemSnippets.*; +import static com.oracle.graal.hotspot.snippets.SystemSubstitutions.*; import static com.oracle.graal.java.GraphBuilderPhase.*; import static com.oracle.graal.nodes.UnwindNode.*; import static com.oracle.graal.nodes.java.RegisterFinalizerNode.*; import static com.oracle.graal.snippets.Log.*; -import static com.oracle.graal.snippets.MathSnippetsX86.*; +import static com.oracle.graal.snippets.MathSubstitutionsX86.*; +import static com.oracle.graal.api.code.CallingConvention.Type.*; import java.lang.reflect.*; import java.util.*; @@ -164,11 +166,14 @@ return globalStubRegConfig.getReturnRegister(kind).asValue(kind); } - protected Value arg(int index, Kind kind) { - if (kind == Kind.Float || kind == Kind.Double) { - return globalStubRegConfig.getCallingConventionRegisters(CallingConvention.Type.RuntimeCall, RegisterFlag.FPU)[index].asValue(kind); - } - return globalStubRegConfig.getCallingConventionRegisters(CallingConvention.Type.RuntimeCall, RegisterFlag.CPU)[index].asValue(kind); + protected Value jarg(int index, Kind kind) { + RegisterFlag flag = kind == Kind.Float || kind == Kind.Double ? FPU : CPU; + return globalStubRegConfig.getCallingConventionRegisters(RuntimeCall, flag)[index].asValue(kind); + } + + protected Value carg(int index, Kind kind) { + RegisterFlag flag = kind == Kind.Float || kind == Kind.Double ? FPU : CPU; + return globalStubRegConfig.getCallingConventionRegisters(NativeCall, flag)[index].asValue(kind); } protected Value scratch(Kind kind) { @@ -184,17 +189,17 @@ addRuntimeCall(UNWIND_EXCEPTION, config.unwindExceptionStub, /* temps */ null, /* ret */ ret(Kind.Void), - /* arg0: exception */ arg(0, Kind.Object)); + /* arg0: exception */ jarg(0, Kind.Object)); addRuntimeCall(OnStackReplacementPhase.OSR_MIGRATION_END, config.osrMigrationEndStub, /* temps */ null, /* ret */ ret(Kind.Void), - /* arg0: long */ arg(0, Kind.Long)); + /* arg0: long */ jarg(0, Kind.Long)); addRuntimeCall(REGISTER_FINALIZER, config.registerFinalizerStub, /* temps */ null, /* ret */ ret(Kind.Void), - /* arg0: object */ arg(0, Kind.Object)); + /* arg0: object */ jarg(0, Kind.Object)); addRuntimeCall(CREATE_NULL_POINTER_EXCEPTION, config.createNullPointerExceptionStub, /* temps */ null, @@ -203,7 +208,7 @@ addRuntimeCall(CREATE_OUT_OF_BOUNDS_EXCEPTION, config.createOutOfBoundsExceptionStub, /* temps */ null, /* ret */ ret(Kind.Object), - /* arg0: index */ arg(0, Kind.Int)); + /* arg0: index */ jarg(0, Kind.Int)); addRuntimeCall(JAVA_TIME_MILLIS, config.javaTimeMillisStub, /* temps */ null, @@ -216,38 +221,38 @@ addRuntimeCall(ARITHMETIC_SIN, config.arithmeticSinStub, /* temps */ null, /* ret */ ret(Kind.Double), - /* arg0: index */ arg(0, Kind.Double)); + /* arg0: index */ jarg(0, Kind.Double)); addRuntimeCall(ARITHMETIC_COS, config.arithmeticCosStub, /* temps */ null, /* ret */ ret(Kind.Double), - /* arg0: index */ arg(0, Kind.Double)); + /* arg0: index */ jarg(0, Kind.Double)); addRuntimeCall(ARITHMETIC_TAN, config.arithmeticTanStub, /* temps */ null, /* ret */ ret(Kind.Double), - /* arg0: index */ arg(0, Kind.Double)); + /* arg0: index */ jarg(0, Kind.Double)); addRuntimeCall(LOG_PRIMITIVE, config.logPrimitiveStub, /* temps */ null, /* ret */ ret(Kind.Void), - /* arg0: typeChar */ arg(0, Kind.Int), - /* arg1: value */ arg(1, Kind.Long), - /* arg2: newline */ arg(2, Kind.Boolean)); + /* arg0: typeChar */ jarg(0, Kind.Int), + /* arg1: value */ jarg(1, Kind.Long), + /* arg2: newline */ jarg(2, Kind.Boolean)); addRuntimeCall(LOG_PRINTF, config.logPrintfStub, /* temps */ null, /* ret */ ret(Kind.Void), - /* arg0: format */ arg(0, Kind.Object), - /* arg1: value */ arg(1, Kind.Long), - /* arg2: value */ arg(2, Kind.Long), - /* arg3: value */ arg(3, Kind.Long)); + /* arg0: format */ jarg(0, Kind.Object), + /* arg1: value */ jarg(1, Kind.Long), + /* arg2: value */ jarg(2, Kind.Long), + /* arg3: value */ jarg(3, Kind.Long)); addRuntimeCall(LOG_OBJECT, config.logObjectStub, /* temps */ null, /* ret */ ret(Kind.Void), - /* arg0: object */ arg(0, Kind.Object), - /* arg1: flags */ arg(1, Kind.Int)); + /* arg0: object */ jarg(0, Kind.Object), + /* arg1: flags */ jarg(1, Kind.Int)); } @@ -303,31 +308,35 @@ public void installSnippets(SnippetInstaller installer, Assumptions assumptions) { if (GraalOptions.IntrinsifyObjectMethods) { - installer.install(ObjectSnippets.class); + installer.installSubstitutions(ObjectSubstitutions.class); } if (GraalOptions.IntrinsifySystemMethods) { - installer.install(SystemSnippets.class); + installer.installSubstitutions(SystemSubstitutions.class); } if (GraalOptions.IntrinsifyThreadMethods) { - installer.install(ThreadSnippets.class); + installer.installSubstitutions(ThreadSubstitutions.class); } if (GraalOptions.IntrinsifyUnsafeMethods) { - installer.install(UnsafeSnippets.class); + installer.installSubstitutions(UnsafeSubstitutions.class); } if (GraalOptions.IntrinsifyClassMethods) { - installer.install(ClassSnippets.class); + installer.installSubstitutions(ClassSubstitutions.class); + } + if (GraalOptions.IntrinsifyAESMethods) { + installer.installSubstitutions(AESCryptSubstitutions.class); + installer.installSubstitutions(CipherBlockChainingSubstitutions.class); } if (GraalOptions.IntrinsifyArrayCopy) { - installer.install(ArrayCopySnippets.class); + installer.installSnippets(ArrayCopySnippets.class); } - installer.install(CheckCastSnippets.class); - installer.install(InstanceOfSnippets.class); - installer.install(NewObjectSnippets.class); - installer.install(MonitorSnippets.class); + installer.installSnippets(CheckCastSnippets.class); + installer.installSnippets(InstanceOfSnippets.class); + installer.installSnippets(NewObjectSnippets.class); + installer.installSnippets(MonitorSnippets.class); - installer.install(NewInstanceStub.class); - installer.install(NewArrayStub.class); + installer.installSnippets(NewInstanceStub.class); + installer.installSnippets(NewArrayStub.class); checkcastSnippets = new CheckCastSnippets.Templates(this, assumptions, graalRuntime.getTarget()); instanceofSnippets = new InstanceOfSnippets.Templates(this, assumptions, graalRuntime.getTarget()); @@ -458,6 +467,11 @@ } @Override + public Signature parseMethodDescriptor(String signature) { + return new HotSpotSignature(signature); + } + + @Override public int getSizeOfLockData() { return config.basicLockSize; } @@ -702,6 +716,8 @@ newObjectSnippets.lower((InitializeArrayNode) n, tool); } else if (n instanceof NewMultiArrayNode) { newObjectSnippets.lower((NewMultiArrayNode) n, tool); + } else if (n instanceof IntegerDivNode || n instanceof IntegerRemNode || n instanceof UnsignedDivNode || n instanceof UnsignedRemNode) { + // Nothing to do for division nodes. The HotSpot signal handler catches divisions by zero and the MIN_VALUE / -1 cases. } else { assert false : "Node implementing Lowerable not handled: " + n; throw GraalInternalError.shouldNotReachHere(); diff -r 36dafe48bc38 -r 42b6e0905881 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotSignature.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotSignature.java Wed Jan 16 09:05:48 2013 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotSignature.java Wed Jan 16 09:08:24 2013 +0100 @@ -25,6 +25,7 @@ import java.util.*; import com.oracle.graal.api.meta.*; +import com.oracle.graal.graph.*; import com.oracle.graal.hotspot.*; import com.oracle.graal.java.*; @@ -86,7 +87,7 @@ case 'Z': break; default: - assert false; + throw new GraalInternalError("Invalid character at index " + cur + " in signature: " + signature); } return cur; } @@ -123,7 +124,8 @@ return type; } - public String asString() { + @Override + public String getMethodDescriptor() { return originalString; } diff -r 36dafe48bc38 -r 42b6e0905881 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/snippets/AESCryptSubstitutions.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/snippets/AESCryptSubstitutions.java Wed Jan 16 09:08:24 2013 +0100 @@ -0,0 +1,127 @@ +/* + * 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.snippets.HotSpotSnippetUtils.*; +import sun.misc.*; + +import com.oracle.graal.api.code.*; +import com.oracle.graal.api.code.RuntimeCallTarget.Descriptor; +import com.oracle.graal.api.meta.*; +import com.oracle.graal.compiler.gen.*; +import com.oracle.graal.compiler.target.*; +import com.oracle.graal.graph.*; +import com.oracle.graal.hotspot.nodes.*; +import com.oracle.graal.nodes.*; +import com.oracle.graal.nodes.type.*; +import com.oracle.graal.snippets.*; +import com.oracle.graal.snippets.ClassSubstitution.MethodSubstitution; +import com.oracle.graal.word.*; + +/** + * Substitutions for {@code com.sun.crypto.provider.AESCrypt} methods. + */ +@ClassSubstitution(className = "com.sun.crypto.provider.AESCrypt") +public class AESCryptSubstitutions { + + static final long kOffset; + static final Class AESCryptClass; + + static { + try { + // Need to use launcher class path as com.sun.crypto.provider.AESCrypt + // is normally not on the boot class path + ClassLoader cl = Launcher.getLauncher().getClassLoader(); + AESCryptClass = Class.forName("com.sun.crypto.provider.AESCrypt", true, cl); + kOffset = UnsafeAccess.unsafe.objectFieldOffset(AESCryptClass.getDeclaredField("K")); + } catch (Exception ex) { + throw new GraalInternalError(ex); + } + } + + @MethodSubstitution(isStatic = false) + static void encryptBlock(Object rcvr, byte[] in, int inOffset, byte[] out, int outOffset) { + Word kAddr = Word.fromObject(rcvr).readWord(Word.unsigned(kOffset)).add(arrayBaseOffset(Kind.Byte)); + Word inAddr = Word.unsigned(GetObjectAddressNode.get(in) + arrayBaseOffset(Kind.Byte) + inOffset); + Word outAddr = Word.unsigned(GetObjectAddressNode.get(out) + arrayBaseOffset(Kind.Byte) + outOffset); + EncryptBlockStubCall.call(inAddr, outAddr, kAddr); + } + + @MethodSubstitution(isStatic = false) + static void decryptBlock(Object rcvr, byte[] in, int inOffset, byte[] out, int outOffset) { + Word kAddr = Word.unsigned(GetObjectAddressNode.get(rcvr)).readWord(Word.unsigned(kOffset)).add(arrayBaseOffset(Kind.Byte)); + Word inAddr = Word.unsigned(GetObjectAddressNode.get(in) + arrayBaseOffset(Kind.Byte) + inOffset); + Word outAddr = Word.unsigned(GetObjectAddressNode.get(out) + arrayBaseOffset(Kind.Byte) + outOffset); + DecryptBlockStubCall.call(inAddr, outAddr, kAddr); + } + + public static class EncryptBlockStubCall extends FixedWithNextNode implements LIRGenLowerable { + + @Input private final ValueNode in; + @Input private final ValueNode out; + @Input private final ValueNode key; + + public static final Descriptor ENCRYPT_BLOCK = new Descriptor("encrypt_block", false, void.class, Word.class, Word.class, Word.class); + + public EncryptBlockStubCall(ValueNode in, ValueNode out, ValueNode key) { + super(StampFactory.forVoid()); + this.in = in; + this.out = out; + this.key = key; + } + + @Override + public void generate(LIRGenerator gen) { + RuntimeCallTarget stub = gen.getRuntime().lookupRuntimeCall(ENCRYPT_BLOCK); + gen.emitCall(stub, stub.getCallingConvention(), false, gen.operand(in), gen.operand(out), gen.operand(key)); + } + + @NodeIntrinsic + public static native void call(Word in, Word out, Word key); + } + + public static class DecryptBlockStubCall extends FixedWithNextNode implements LIRGenLowerable { + + @Input private final ValueNode in; + @Input private final ValueNode out; + @Input private final ValueNode key; + + public static final Descriptor DECRYPT_BLOCK = new Descriptor("decrypt_block", false, void.class, Word.class, Word.class, Word.class); + + public DecryptBlockStubCall(ValueNode in, ValueNode out, ValueNode key) { + super(StampFactory.forVoid()); + this.in = in; + this.out = out; + this.key = key; + } + + @Override + public void generate(LIRGenerator gen) { + RuntimeCallTarget stub = gen.getRuntime().lookupRuntimeCall(DECRYPT_BLOCK); + gen.emitCall(stub, stub.getCallingConvention(), false, gen.operand(in), gen.operand(out), gen.operand(key)); + } + + @NodeIntrinsic + public static native void call(Word in, Word out, Word key); + } +} diff -r 36dafe48bc38 -r 42b6e0905881 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/snippets/CheckCastSnippets.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/snippets/CheckCastSnippets.java Wed Jan 16 09:05:48 2013 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/snippets/CheckCastSnippets.java Wed Jan 16 09:08:24 2013 +0100 @@ -25,6 +25,7 @@ import static com.oracle.graal.hotspot.snippets.HotSpotSnippetUtils.*; import static com.oracle.graal.snippets.SnippetTemplate.*; import static com.oracle.graal.snippets.SnippetTemplate.Arguments.*; +import static com.oracle.graal.snippets.nodes.BranchProbabilityNode.*; import com.oracle.graal.api.code.*; import com.oracle.graal.api.meta.*; @@ -68,11 +69,13 @@ @Parameter("exactHub") Word exactHub, @ConstantParameter("checkNull") boolean checkNull) { if (checkNull && object == null) { + probability(0.1); isNull.inc(); return object; } Word objectHub = loadHub(object); if (objectHub != exactHub) { + probability(0.01); exactMiss.inc(); //bkpt(object, exactHub, objectHub); DeoptimizeNode.deopt(DeoptimizationAction.InvalidateReprofile, DeoptimizationReason.ClassCastException); diff -r 36dafe48bc38 -r 42b6e0905881 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/snippets/CipherBlockChainingSubstitutions.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/snippets/CipherBlockChainingSubstitutions.java Wed Jan 16 09:08:24 2013 +0100 @@ -0,0 +1,152 @@ +/* + * 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.snippets.HotSpotSnippetUtils.*; +import sun.misc.*; + +import com.oracle.graal.api.code.*; +import com.oracle.graal.api.code.RuntimeCallTarget.Descriptor; +import com.oracle.graal.api.meta.*; +import com.oracle.graal.compiler.gen.*; +import com.oracle.graal.compiler.target.*; +import com.oracle.graal.graph.*; +import com.oracle.graal.hotspot.nodes.*; +import com.oracle.graal.nodes.*; +import com.oracle.graal.nodes.type.*; +import com.oracle.graal.snippets.*; +import com.oracle.graal.snippets.ClassSubstitution.MethodSubstitution; +import com.oracle.graal.snippets.Snippet.Fold; +import com.oracle.graal.word.*; + +/** + * Substitutions for {@code com.sun.crypto.provider.CipherBlockChaining} methods. + */ +@ClassSubstitution(className = "com.sun.crypto.provider.CipherBlockChaining") +public class CipherBlockChainingSubstitutions { + + private static final long embeddedCipherOffset; + private static final long rOffset; + static { + try { + // Need to use launcher class path as com.sun.crypto.provider.AESCrypt + // is normally not on the boot class path + ClassLoader cl = Launcher.getLauncher().getClassLoader(); + embeddedCipherOffset = UnsafeAccess.unsafe.objectFieldOffset(Class.forName("com.sun.crypto.provider.FeedbackCipher", true, cl).getDeclaredField("embeddedCipher")); + rOffset = UnsafeAccess.unsafe.objectFieldOffset(Class.forName("com.sun.crypto.provider.CipherBlockChaining", true, cl).getDeclaredField("r")); + } catch (Exception ex) { + throw new GraalInternalError(ex); + } + } + + @Fold + private static Class getAESCryptClass() { + return AESCryptSubstitutions.AESCryptClass; + } + + @MethodSubstitution(isStatic = false) + static void encrypt(Object rcvr, byte[] in, int inOffset, int inLength, byte[] out, int outOffset) { + Object embeddedCipher = Word.fromObject(rcvr).readObject(Word.unsigned(embeddedCipherOffset)); + if (getAESCryptClass().isInstance(embeddedCipher)) { + Word kAddr = Word.fromObject(embeddedCipher).readWord(Word.unsigned(AESCryptSubstitutions.kOffset)).add(arrayBaseOffset(Kind.Byte)); + Word rAddr = Word.unsigned(GetObjectAddressNode.get(rcvr)).readWord(Word.unsigned(rOffset)).add(arrayBaseOffset(Kind.Byte)); + Word inAddr = Word.unsigned(GetObjectAddressNode.get(in) + arrayBaseOffset(Kind.Byte) + inOffset); + Word outAddr = Word.unsigned(GetObjectAddressNode.get(out) + arrayBaseOffset(Kind.Byte) + outOffset); + EncryptAESCryptStubCall.call(inAddr, outAddr, kAddr, rAddr, inLength); + } else { + encrypt(rcvr, in, inOffset, inLength, out, outOffset); + } + } + + @MethodSubstitution(isStatic = false) + static void decrypt(Object rcvr, byte[] in, int inOffset, int inLength, byte[] out, int outOffset) { + Object embeddedCipher = Word.fromObject(rcvr).readObject(Word.unsigned(embeddedCipherOffset)); + if (in != out && getAESCryptClass().isInstance(embeddedCipher)) { + Word kAddr = Word.fromObject(embeddedCipher).readWord(Word.unsigned(AESCryptSubstitutions.kOffset)).add(arrayBaseOffset(Kind.Byte)); + Word rAddr = Word.unsigned(GetObjectAddressNode.get(rcvr)).readWord(Word.unsigned(rOffset)).add(arrayBaseOffset(Kind.Byte)); + Word inAddr = Word.unsigned(GetObjectAddressNode.get(in) + arrayBaseOffset(Kind.Byte) + inOffset); + Word outAddr = Word.unsigned(GetObjectAddressNode.get(out) + arrayBaseOffset(Kind.Byte) + outOffset); + DecryptAESCryptStubCall.call(inAddr, outAddr, kAddr, rAddr, inLength); + } else { + decrypt(rcvr, in, inOffset, inLength, out, outOffset); + } + } + + public static class EncryptAESCryptStubCall extends FixedWithNextNode implements LIRGenLowerable { + + @Input private final ValueNode in; + @Input private final ValueNode out; + @Input private final ValueNode key; + @Input private final ValueNode r; + @Input private final ValueNode inLength; + + public static final Descriptor ENCRYPT = new Descriptor("encrypt", false, void.class, Word.class, Word.class, Word.class, Word.class, int.class); + + public EncryptAESCryptStubCall(ValueNode in, ValueNode out, ValueNode key, ValueNode r, ValueNode inLength) { + super(StampFactory.forVoid()); + this.in = in; + this.out = out; + this.key = key; + this.r = r; + this.inLength = inLength; + } + + @Override + public void generate(LIRGenerator gen) { + RuntimeCallTarget stub = gen.getRuntime().lookupRuntimeCall(ENCRYPT); + gen.emitCall(stub, stub.getCallingConvention(), false, gen.operand(in), gen.operand(out), gen.operand(key), gen.operand(r), gen.operand(inLength)); + } + + @NodeIntrinsic + public static native void call(Word in, Word out, Word key, Word r, int inLength); + } + + public static class DecryptAESCryptStubCall extends FixedWithNextNode implements LIRGenLowerable { + + @Input private final ValueNode in; + @Input private final ValueNode out; + @Input private final ValueNode key; + @Input private final ValueNode r; + @Input private final ValueNode inLength; + + public static final Descriptor DECRYPT = new Descriptor("decrypt", false, void.class, Word.class, Word.class, Word.class, Word.class, int.class); + + public DecryptAESCryptStubCall(ValueNode in, ValueNode out, ValueNode key, ValueNode r, ValueNode inLength) { + super(StampFactory.forVoid()); + this.in = in; + this.out = out; + this.key = key; + this.r = r; + this.inLength = inLength; + } + + @Override + public void generate(LIRGenerator gen) { + RuntimeCallTarget stub = gen.getRuntime().lookupRuntimeCall(DECRYPT); + gen.emitCall(stub, stub.getCallingConvention(), false, gen.operand(in), gen.operand(out), gen.operand(key), gen.operand(r), gen.operand(inLength)); + } + + @NodeIntrinsic + public static native void call(Word in, Word out, Word key, Word r, int inLength); + } +} diff -r 36dafe48bc38 -r 42b6e0905881 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/snippets/ClassSnippets.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/snippets/ClassSnippets.java Wed Jan 16 09:05:48 2013 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,117 +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.snippets.HotSpotSnippetUtils.*; -import static com.oracle.graal.nodes.extended.UnsafeCastNode.*; - -import java.lang.reflect.*; - -import com.oracle.graal.nodes.*; -import com.oracle.graal.snippets.*; -import com.oracle.graal.snippets.ClassSubstitution.MethodSubstitution; -import com.oracle.graal.word.*; - -/** - * Snippets for {@link java.lang.Class} methods. - */ -@ClassSubstitution(java.lang.Class.class) -public class ClassSnippets implements SnippetsInterface { - @MethodSubstitution(isStatic = false) - public static int getModifiers(final Class thisObj) { - Word klass = loadWordFromObject(thisObj, klassOffset()); - if (klass == Word.zero()) { - // Class for primitive type - return Modifier.ABSTRACT | Modifier.FINAL | Modifier.PUBLIC; - } else { - return klass.readInt(klassModifierFlagsOffset()); - } - } - - @MethodSubstitution(isStatic = false) - public static boolean isInterface(final Class thisObj) { - Word klass = loadWordFromObject(thisObj, klassOffset()); - if (klass == Word.zero()) { - return false; - } else { - int accessFlags = klass.readInt(klassAccessFlagsOffset()); - return (accessFlags & Modifier.INTERFACE) != 0; - } - } - - @MethodSubstitution(isStatic = false) - public static boolean isArray(final Class thisObj) { - Word klass = loadWordFromObject(thisObj, klassOffset()); - if (klass == Word.zero()) { - return false; - } else { - int layoutHelper = klass.readInt(klassLayoutHelperOffset()); - return (layoutHelper & arrayKlassLayoutHelperIdentifier()) != 0; - } - } - - @MethodSubstitution(isStatic = false) - public static boolean isPrimitive(final Class thisObj) { - Word klass = loadWordFromObject(thisObj, klassOffset()); - return klass == Word.zero(); - } - - @MethodSubstitution(isStatic = false) - public static Class getSuperclass(final Class thisObj) { - Word klass = loadWordFromObject(thisObj, klassOffset()); - if (klass != Word.zero()) { - int accessFlags = klass.readInt(klassAccessFlagsOffset()); - if ((accessFlags & Modifier.INTERFACE) == 0) { - int layoutHelper = klass.readInt(klassLayoutHelperOffset()); - if ((layoutHelper & arrayKlassLayoutHelperIdentifier()) != 0) { - return Object.class; - } else { - Word superKlass = klass.readWord(klassSuperKlassOffset()); - if (superKlass == Word.zero()) { - return null; - } else { - return unsafeCast(superKlass.readObject(classMirrorOffset()), Class.class, true, true); - } - } - } - } - return null; - } - - @MethodSubstitution(isStatic = false) - public static Class getComponentType(final Class thisObj) { - Word klass = loadWordFromObject(thisObj, klassOffset()); - if (klass != Word.zero()) { - int layoutHelper = klass.readInt(klassLayoutHelperOffset()); - if ((layoutHelper & arrayKlassLayoutHelperIdentifier()) != 0) { - return unsafeCast(klass.readObject(arrayKlassComponentMirrorOffset()), Class.class, true, true); - } - } - return null; - } - - @MethodSubstitution(isStatic = false) - public static boolean isInstance(final Class thisObj, Object obj) { - return !thisObj.isPrimitive() && MaterializeNode.isInstance(thisObj, obj); - } -} diff -r 36dafe48bc38 -r 42b6e0905881 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/snippets/ClassSubstitutions.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/snippets/ClassSubstitutions.java Wed Jan 16 09:08:24 2013 +0100 @@ -0,0 +1,117 @@ +/* + * 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.snippets.HotSpotSnippetUtils.*; +import static com.oracle.graal.nodes.extended.UnsafeCastNode.*; + +import java.lang.reflect.*; + +import com.oracle.graal.nodes.*; +import com.oracle.graal.snippets.*; +import com.oracle.graal.snippets.ClassSubstitution.MethodSubstitution; +import com.oracle.graal.word.*; + +/** + * Substitutions for {@link java.lang.Class} methods. + */ +@ClassSubstitution(java.lang.Class.class) +public class ClassSubstitutions { + @MethodSubstitution(isStatic = false) + public static int getModifiers(final Class thisObj) { + Word klass = loadWordFromObject(thisObj, klassOffset()); + if (klass == Word.zero()) { + // Class for primitive type + return Modifier.ABSTRACT | Modifier.FINAL | Modifier.PUBLIC; + } else { + return klass.readInt(klassModifierFlagsOffset()); + } + } + + @MethodSubstitution(isStatic = false) + public static boolean isInterface(final Class thisObj) { + Word klass = loadWordFromObject(thisObj, klassOffset()); + if (klass == Word.zero()) { + return false; + } else { + int accessFlags = klass.readInt(klassAccessFlagsOffset()); + return (accessFlags & Modifier.INTERFACE) != 0; + } + } + + @MethodSubstitution(isStatic = false) + public static boolean isArray(final Class thisObj) { + Word klass = loadWordFromObject(thisObj, klassOffset()); + if (klass == Word.zero()) { + return false; + } else { + int layoutHelper = klass.readInt(klassLayoutHelperOffset()); + return (layoutHelper & arrayKlassLayoutHelperIdentifier()) != 0; + } + } + + @MethodSubstitution(isStatic = false) + public static boolean isPrimitive(final Class thisObj) { + Word klass = loadWordFromObject(thisObj, klassOffset()); + return klass == Word.zero(); + } + + @MethodSubstitution(isStatic = false) + public static Class getSuperclass(final Class thisObj) { + Word klass = loadWordFromObject(thisObj, klassOffset()); + if (klass != Word.zero()) { + int accessFlags = klass.readInt(klassAccessFlagsOffset()); + if ((accessFlags & Modifier.INTERFACE) == 0) { + int layoutHelper = klass.readInt(klassLayoutHelperOffset()); + if ((layoutHelper & arrayKlassLayoutHelperIdentifier()) != 0) { + return Object.class; + } else { + Word superKlass = klass.readWord(klassSuperKlassOffset()); + if (superKlass == Word.zero()) { + return null; + } else { + return unsafeCast(superKlass.readObject(classMirrorOffset()), Class.class, true, true); + } + } + } + } + return null; + } + + @MethodSubstitution(isStatic = false) + public static Class getComponentType(final Class thisObj) { + Word klass = loadWordFromObject(thisObj, klassOffset()); + if (klass != Word.zero()) { + int layoutHelper = klass.readInt(klassLayoutHelperOffset()); + if ((layoutHelper & arrayKlassLayoutHelperIdentifier()) != 0) { + return unsafeCast(klass.readObject(arrayKlassComponentMirrorOffset()), Class.class, true, true); + } + } + return null; + } + + @MethodSubstitution(isStatic = false) + public static boolean isInstance(final Class thisObj, Object obj) { + return !thisObj.isPrimitive() && MaterializeNode.isInstance(thisObj, obj); + } +} diff -r 36dafe48bc38 -r 42b6e0905881 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/snippets/InstanceOfSnippets.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/snippets/InstanceOfSnippets.java Wed Jan 16 09:05:48 2013 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/snippets/InstanceOfSnippets.java Wed Jan 16 09:08:24 2013 +0100 @@ -26,6 +26,7 @@ import static com.oracle.graal.hotspot.snippets.CheckCastSnippets.Templates.*; import static com.oracle.graal.hotspot.snippets.HotSpotSnippetUtils.*; import static com.oracle.graal.snippets.SnippetTemplate.Arguments.*; +import static com.oracle.graal.snippets.nodes.BranchProbabilityNode.*; import com.oracle.graal.api.code.*; import com.oracle.graal.api.meta.*; @@ -66,11 +67,13 @@ @Parameter("falseValue") Object falseValue, @ConstantParameter("checkNull") boolean checkNull) { if (checkNull && object == null) { + probability(0.01); isNull.inc(); return falseValue; } Word objectHub = loadHub(object); if (objectHub != exactHub) { + probability(0.75); exactMiss.inc(); return falseValue; } @@ -90,11 +93,13 @@ @ConstantParameter("checkNull") boolean checkNull, @ConstantParameter("superCheckOffset") int superCheckOffset) { if (checkNull && object == null) { + probability(0.01); isNull.inc(); return falseValue; } Word objectHub = loadHub(object); if (objectHub.readWord(superCheckOffset) != hub) { + probability(0.45); displayMiss.inc(); return falseValue; } @@ -114,6 +119,7 @@ @VarargsParameter("hints") Word[] hints, @ConstantParameter("checkNull") boolean checkNull) { if (checkNull && object == null) { + probability(0.01); isNull.inc(); return falseValue; } @@ -123,6 +129,7 @@ for (int i = 0; i < hints.length; i++) { Word hintHub = hints[i]; if (hintHub == objectHub) { + probability(0.01); hintsHit.inc(); return trueValue; } @@ -151,6 +158,7 @@ int length = secondarySupers.readInt(metaspaceArrayLengthOffset()); for (int i = 0; i < length; i++) { if (t == loadWordElement(secondarySupers, i)) { + probability(0.01); s.writeWord(secondarySuperCacheOffset(), t); secondariesHit.inc(); return true; @@ -171,6 +179,7 @@ @Parameter("falseValue") Object falseValue, @ConstantParameter("checkNull") boolean checkNull) { if (checkNull && object == null) { + probability(0.01); isNull.inc(); return falseValue; } @@ -240,7 +249,7 @@ } } - private static final SnippetCounter.Group counters = GraalOptions.SnippetCounters ? new SnippetCounter.Group("Checkcast") : null; + private static final SnippetCounter.Group counters = GraalOptions.SnippetCounters ? new SnippetCounter.Group("InstanceOf") : 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"); diff -r 36dafe48bc38 -r 42b6e0905881 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/snippets/IntrinsifyArrayCopyPhase.java diff -r 36dafe48bc38 -r 42b6e0905881 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/snippets/NewObjectSnippets.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/snippets/NewObjectSnippets.java Wed Jan 16 09:05:48 2013 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/snippets/NewObjectSnippets.java Wed Jan 16 09:08:24 2013 +0100 @@ -30,6 +30,7 @@ import static com.oracle.graal.snippets.SnippetTemplate.*; import static com.oracle.graal.snippets.SnippetTemplate.Arguments.*; import static com.oracle.graal.snippets.nodes.ExplodeLoopNode.*; +import static com.oracle.graal.snippets.nodes.BranchProbabilityNode.*; import com.oracle.graal.api.code.*; import com.oracle.graal.api.meta.*; @@ -64,6 +65,7 @@ Word newTop = top.add(size); // this check might lead to problems if the TLAB is within 16GB of the address space end (checked in c++ code) if (newTop.belowOrEqual(end)) { + probability(0.99); thread.writeWord(threadTlabTopOffset(), newTop); return top; } @@ -84,6 +86,7 @@ new_stub.inc(); result = NewInstanceStubCall.call(hub); } else { + probability(0.99); if (locked) { formatObject(hub, size, memory, thread().or(biasedLockPattern()), fillContents); } else { @@ -117,6 +120,7 @@ newarray_stub.inc(); result = NewArrayStubCall.call(hub, length); } else { + probability(0.99); newarray_loopInit.inc(); formatArray(hub, allocationSize, length, headerSize, memory, prototypeMarkWord, fillContents); result = memory.toObject(); @@ -140,6 +144,7 @@ // This handles both negative array sizes and very large array sizes DeoptimizeNode.deopt(DeoptimizationAction.None, DeoptimizationReason.RuntimeConstraint); } + probability(0.99); int allocationSize = computeArrayAllocationSize(length, alignment, headerSize, log2ElementSize); Word memory = TLABAllocateNode.allocateVariableSize(allocationSize); return InitializeArrayNode.initialize(memory, length, allocationSize, type, true, false); diff -r 36dafe48bc38 -r 42b6e0905881 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/snippets/ObjectSnippets.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/snippets/ObjectSnippets.java Wed Jan 16 09:05:48 2013 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,59 +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.snippets.HotSpotSnippetUtils.*; -import static com.oracle.graal.nodes.extended.UnsafeCastNode.*; - -import com.oracle.graal.hotspot.nodes.*; -import com.oracle.graal.snippets.*; -import com.oracle.graal.snippets.ClassSubstitution.MethodSubstitution; -import com.oracle.graal.word.*; - -/** - * Snippets for {@link java.lang.Object} methods. - */ -@ClassSubstitution(java.lang.Object.class) -public class ObjectSnippets implements SnippetsInterface { - @MethodSubstitution(isStatic = false) - public static Class getClass(final Object thisObj) { - Word hub = loadHub(thisObj); - return unsafeCast(hub.readFinalObject(Word.signed(classMirrorOffset())), Class.class, true, true); - } - - @MethodSubstitution(isStatic = false) - public static int hashCode(final Object thisObj) { - Word mark = loadWordFromObject(thisObj, markOffset()); - - // this code is independent from biased locking (although it does not look that way) - final Word biasedLock = mark.and(biasedLockMaskInPlace()); - if (biasedLock == Word.unsigned(unlockedMask())) { - int hash = (int) mark.unsignedShiftRight(identityHashCodeShift()).rawValue(); - if (hash != uninitializedIdentityHashCodeValue()) { - return hash; - } - } - - return IdentityHashCodeStubCall.call(thisObj); - } -} diff -r 36dafe48bc38 -r 42b6e0905881 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/snippets/ObjectSubstitutions.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/snippets/ObjectSubstitutions.java Wed Jan 16 09:08:24 2013 +0100 @@ -0,0 +1,63 @@ +/* + * 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.snippets.HotSpotSnippetUtils.*; +import static com.oracle.graal.nodes.extended.UnsafeCastNode.*; +import static com.oracle.graal.snippets.nodes.BranchProbabilityNode.*; + +import com.oracle.graal.hotspot.nodes.*; +import com.oracle.graal.snippets.*; +import com.oracle.graal.snippets.ClassSubstitution.MethodSubstitution; +import com.oracle.graal.word.*; + +/** + * Substitutions for {@link java.lang.Object} methods. + */ +@ClassSubstitution(java.lang.Object.class) +public class ObjectSubstitutions { + + @MethodSubstitution(isStatic = false) + public static Class< ? > getClass(final Object thisObj) { + Word hub = loadHub(thisObj); + return unsafeCast(hub.readFinalObject(Word.signed(classMirrorOffset())), Class.class, true, true); + } + + @MethodSubstitution(isStatic = false) + public static int hashCode(final Object thisObj) { + Word mark = loadWordFromObject(thisObj, markOffset()); + + // this code is independent from biased locking (although it does not look that way) + final Word biasedLock = mark.and(biasedLockMaskInPlace()); + if (biasedLock == Word.unsigned(unlockedMask())) { + probability(0.99); + int hash = (int) mark.unsignedShiftRight(identityHashCodeShift()).rawValue(); + if (hash != uninitializedIdentityHashCodeValue()) { + probability(0.99); + return hash; + } + } + + return IdentityHashCodeStubCall.call(thisObj); + } +} diff -r 36dafe48bc38 -r 42b6e0905881 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/snippets/SystemSnippets.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/snippets/SystemSnippets.java Wed Jan 16 09:05:48 2013 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,73 +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.snippets; - -import static com.oracle.graal.hotspot.snippets.HotSpotSnippetUtils.*; - -import com.oracle.graal.api.code.RuntimeCallTarget.Descriptor; -import com.oracle.graal.graph.Node.ConstantNodeParameter; -import com.oracle.graal.graph.Node.NodeIntrinsic; -import com.oracle.graal.hotspot.nodes.*; -import com.oracle.graal.nodes.extended.*; -import com.oracle.graal.snippets.*; -import com.oracle.graal.word.*; - -/** - * Snippets for {@link java.lang.System} methods. - */ -@ClassSubstitution(java.lang.System.class) -public class SystemSnippets implements SnippetsInterface { - - public static final Descriptor JAVA_TIME_MILLIS = new Descriptor("javaTimeMillis", false, long.class); - public static final Descriptor JAVA_TIME_NANOS = new Descriptor("javaTimeNanos", false, long.class); - - public static long currentTimeMillis() { - return callLong(JAVA_TIME_MILLIS); - } - - public static long nanoTime() { - return callLong(JAVA_TIME_NANOS); - } - - public static int identityHashCode(Object x) { - if (x == null) { - return 0; - } - - Word mark = loadWordFromObject(x, markOffset()); - - // this code is independent from biased locking (although it does not look that way) - final Word biasedLock = mark.and(biasedLockMaskInPlace()); - if (biasedLock == Word.unsigned(unlockedMask())) { - int hash = (int) mark.unsignedShiftRight(identityHashCodeShift()).rawValue(); - if (hash != uninitializedIdentityHashCodeValue()) { - return hash; - } - } - - return IdentityHashCodeStubCall.call(x); - } - - @NodeIntrinsic(value = RuntimeCallNode.class, setStampFromReturnType = true) - public static native long callLong(@ConstantNodeParameter Descriptor descriptor); -} diff -r 36dafe48bc38 -r 42b6e0905881 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/snippets/SystemSubstitutions.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/snippets/SystemSubstitutions.java Wed Jan 16 09:08:24 2013 +0100 @@ -0,0 +1,81 @@ +/* + * 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.hotspot.snippets.HotSpotSnippetUtils.*; +import static com.oracle.graal.snippets.nodes.BranchProbabilityNode.*; + +import com.oracle.graal.api.code.RuntimeCallTarget.Descriptor; +import com.oracle.graal.graph.Node.ConstantNodeParameter; +import com.oracle.graal.graph.Node.NodeIntrinsic; +import com.oracle.graal.hotspot.nodes.*; +import com.oracle.graal.nodes.extended.*; +import com.oracle.graal.snippets.*; +import com.oracle.graal.snippets.ClassSubstitution.MethodSubstitution; +import com.oracle.graal.word.*; + +/** + * Substitutions for {@link java.lang.System} methods. + */ +@ClassSubstitution(java.lang.System.class) +public class SystemSubstitutions { + + public static final Descriptor JAVA_TIME_MILLIS = new Descriptor("javaTimeMillis", false, long.class); + public static final Descriptor JAVA_TIME_NANOS = new Descriptor("javaTimeNanos", false, long.class); + + @MethodSubstitution + public static long currentTimeMillis() { + return callLong(JAVA_TIME_MILLIS); + } + + @MethodSubstitution + public static long nanoTime() { + return callLong(JAVA_TIME_NANOS); + } + + @MethodSubstitution + public static int identityHashCode(Object x) { + if (x == null) { + probability(0.01); + return 0; + } + + Word mark = loadWordFromObject(x, markOffset()); + + // this code is independent from biased locking (although it does not look that way) + final Word biasedLock = mark.and(biasedLockMaskInPlace()); + if (biasedLock == Word.unsigned(unlockedMask())) { + probability(0.99); + int hash = (int) mark.unsignedShiftRight(identityHashCodeShift()).rawValue(); + if (hash != uninitializedIdentityHashCodeValue()) { + probability(0.99); + return hash; + } + } + + return IdentityHashCodeStubCall.call(x); + } + + @NodeIntrinsic(value = RuntimeCallNode.class, setStampFromReturnType = true) + public static native long callLong(@ConstantNodeParameter Descriptor descriptor); +} diff -r 36dafe48bc38 -r 42b6e0905881 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/snippets/ThreadSnippets.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/snippets/ThreadSnippets.java Wed Jan 16 09:05:48 2013 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,55 +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.snippets.HotSpotSnippetUtils.*; - -import com.oracle.graal.hotspot.nodes.*; -import com.oracle.graal.snippets.*; -import com.oracle.graal.snippets.ClassSubstitution.MethodSubstitution; -import com.oracle.graal.word.*; - -/** - * Snippets for {@link java.lang.Thread} methods. - */ -@ClassSubstitution(java.lang.Thread.class) -public class ThreadSnippets implements SnippetsInterface { - public static Thread currentThread() { - return CurrentThread.get(); - } - - @MethodSubstitution(isStatic = false) - private static boolean isInterrupted(final Thread thisObject, boolean clearInterrupted) { - Word rawThread = HotSpotCurrentRawThreadNode.get(); - Thread thread = (Thread) rawThread.readObject(threadObjectOffset()); - if (thisObject == thread) { - Word osThread = rawThread.readWord(osThreadOffset()); - boolean interrupted = osThread.readInt(osThreadInterruptedOffset()) != 0; - if (!interrupted || !clearInterrupted) { - return interrupted; - } - } - - return ThreadIsInterruptedStubCall.call(thisObject, clearInterrupted) != 0; - } -} diff -r 36dafe48bc38 -r 42b6e0905881 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/snippets/ThreadSubstitutions.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/snippets/ThreadSubstitutions.java Wed Jan 16 09:08:24 2013 +0100 @@ -0,0 +1,57 @@ +/* + * 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.snippets.HotSpotSnippetUtils.*; + +import com.oracle.graal.hotspot.nodes.*; +import com.oracle.graal.snippets.*; +import com.oracle.graal.snippets.ClassSubstitution.MethodSubstitution; +import com.oracle.graal.word.*; + +/** + * Substitutions for {@link java.lang.Thread} methods. + */ +@ClassSubstitution(java.lang.Thread.class) +public class ThreadSubstitutions { + + @MethodSubstitution + public static Thread currentThread() { + return CurrentThread.get(); + } + + @MethodSubstitution(isStatic = false) + private static boolean isInterrupted(final Thread thisObject, boolean clearInterrupted) { + Word rawThread = HotSpotCurrentRawThreadNode.get(); + Thread thread = (Thread) rawThread.readObject(threadObjectOffset()); + if (thisObject == thread) { + Word osThread = rawThread.readWord(osThreadOffset()); + boolean interrupted = osThread.readInt(osThreadInterruptedOffset()) != 0; + if (!interrupted || !clearInterrupted) { + return interrupted; + } + } + + return ThreadIsInterruptedStubCall.call(thisObject, clearInterrupted) != 0; + } +} diff -r 36dafe48bc38 -r 42b6e0905881 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/NewArrayStub.java diff -r 36dafe48bc38 -r 42b6e0905881 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/NewInstanceStub.java diff -r 36dafe48bc38 -r 42b6e0905881 graal/com.oracle.graal.java/src/com/oracle/graal/java/GraphBuilderPhase.java --- a/graal/com.oracle.graal.java/src/com/oracle/graal/java/GraphBuilderPhase.java Wed Jan 16 09:05:48 2013 +0100 +++ b/graal/com.oracle.graal.java/src/com/oracle/graal/java/GraphBuilderPhase.java Wed Jan 16 09:08:24 2013 +0100 @@ -409,7 +409,7 @@ } - private void genArithmeticOp(Kind result, int opcode, boolean canTrap) { + private void genArithmeticOp(Kind result, int opcode) { ValueNode y = frameState.pop(result); ValueNode x = frameState.pop(result); boolean isStrictFP = isStrict(method.getModifiers()); @@ -427,21 +427,30 @@ case LMUL: v = new IntegerMulNode(result, x, y); break; case FMUL: case DMUL: v = new FloatMulNode(result, x, y, isStrictFP); break; - case IDIV: - case LDIV: v = new IntegerDivNode(result, x, y); break; case FDIV: case DDIV: v = new FloatDivNode(result, x, y, isStrictFP); break; - case IREM: - case LREM: v = new IntegerRemNode(result, x, y); break; case FREM: case DREM: v = new FloatRemNode(result, x, y, isStrictFP); break; default: throw new GraalInternalError("should not reach"); } ValueNode result1 = append(currentGraph.unique(v)); - if (canTrap) { - append(currentGraph.add(new ValueAnchorNode(result1))); + frameState.push(result, result1); + } + + private void genIntegerDivOp(Kind result, int opcode) { + ValueNode y = frameState.pop(result); + ValueNode x = frameState.pop(result); + FixedWithNextNode v; + switch(opcode){ + case IDIV: + case LDIV: v = new IntegerDivNode(result, x, y); break; + case IREM: + case LREM: v = new IntegerRemNode(result, x, y); break; + default: + throw new GraalInternalError("should not reach"); } + ValueNode result1 = append(currentGraph.add(v)); frameState.push(result, result1); } @@ -1680,24 +1689,24 @@ case SWAP : stackOp(opcode); break; case IADD : // fall through case ISUB : // fall through - case IMUL : genArithmeticOp(Kind.Int, opcode, false); break; + case IMUL : genArithmeticOp(Kind.Int, opcode); break; case IDIV : // fall through - case IREM : genArithmeticOp(Kind.Int, opcode, true); break; + case IREM : genIntegerDivOp(Kind.Int, opcode); break; case LADD : // fall through case LSUB : // fall through - case LMUL : genArithmeticOp(Kind.Long, opcode, false); break; + case LMUL : genArithmeticOp(Kind.Long, opcode); break; case LDIV : // fall through - case LREM : genArithmeticOp(Kind.Long, opcode, true); break; + case LREM : genIntegerDivOp(Kind.Long, opcode); break; case FADD : // fall through case FSUB : // fall through case FMUL : // fall through case FDIV : // fall through - case FREM : genArithmeticOp(Kind.Float, opcode, false); break; + case FREM : genArithmeticOp(Kind.Float, opcode); break; case DADD : // fall through case DSUB : // fall through case DMUL : // fall through case DDIV : // fall through - case DREM : genArithmeticOp(Kind.Double, opcode, false); break; + case DREM : genArithmeticOp(Kind.Double, opcode); break; case INEG : genNegateOp(Kind.Int); break; case LNEG : genNegateOp(Kind.Long); break; case FNEG : genNegateOp(Kind.Float); break; diff -r 36dafe48bc38 -r 42b6e0905881 graal/com.oracle.graal.lir.amd64/src/com/oracle/graal/lir/amd64/AMD64Arithmetic.java --- a/graal/com.oracle.graal.lir.amd64/src/com/oracle/graal/lir/amd64/AMD64Arithmetic.java Wed Jan 16 09:05:48 2013 +0100 +++ b/graal/com.oracle.graal.lir.amd64/src/com/oracle/graal/lir/amd64/AMD64Arithmetic.java Wed Jan 16 09:08:24 2013 +0100 @@ -35,8 +35,8 @@ import com.oracle.graal.lir.asm.*; public enum AMD64Arithmetic { - IADD, ISUB, IMUL, IDIV, IREM, IUDIV, IUREM, IAND, IOR, IXOR, ISHL, ISHR, IUSHR, - LADD, LSUB, LMUL, LDIV, LREM, LUDIV, LUREM, LAND, LOR, LXOR, LSHL, LSHR, LUSHR, + IADD, ISUB, IMUL, IDIV, IDIVREM, IREM, IUDIV, IUREM, IAND, IOR, IXOR, ISHL, ISHR, IUSHR, + LADD, LSUB, LMUL, LDIV, LDIVREM, LREM, LUDIV, LUREM, LAND, LOR, LXOR, LSHL, LSHR, LUSHR, FADD, FSUB, FMUL, FDIV, FAND, FOR, FXOR, DADD, DSUB, DMUL, DDIV, DAND, DOR, DXOR, INEG, LNEG, @@ -195,6 +195,39 @@ } } + public static class DivRemOp extends AMD64LIRInstruction { + @Opcode private final AMD64Arithmetic opcode; + @Def protected Value divResult; + @Def protected Value remResult; + @Use protected Value x; + @Alive protected Value y; + @State protected LIRFrameState state; + + public DivRemOp(AMD64Arithmetic opcode, Value x, Value y, LIRFrameState state) { + this.opcode = opcode; + this.divResult = AMD64.rax.asValue(x.getKind()); + this.remResult = AMD64.rdx.asValue(x.getKind()); + this.x = x; + this.y = y; + this.state = state; + } + + @Override + public void emitCode(TargetMethodAssembler tasm, AMD64MacroAssembler masm) { + emit(tasm, masm, opcode, null, y, state); + } + + @Override + protected void verify() { + super.verify(); + // left input in rax, right input in any register but rax and rdx, result quotient in rax, result remainder in rdx + assert asRegister(x) == AMD64.rax; + assert differentRegisters(y, AMD64.rax.asValue(), AMD64.rdx.asValue()); + verifyKind(opcode, divResult, x, y); + verifyKind(opcode, remResult, x, y); + } + } + public static class DivOp extends AMD64LIRInstruction { @Opcode private final AMD64Arithmetic opcode; @Def protected Value result; @@ -310,6 +343,7 @@ case MOV_F2I: masm.movdl(asIntReg(dst), asFloatReg(src)); break; case MOV_D2L: masm.movdq(asLongReg(dst), asDoubleReg(src)); break; + case IDIVREM: case IDIV: case IREM: masm.cdql(); @@ -317,24 +351,12 @@ masm.idivl(asRegister(src)); break; + case LDIVREM: case LDIV: case LREM: - Label continuation = new Label(); - if (opcode == LDIV) { - // check for special case of Long.MIN_VALUE / -1 - Label normalCase = new Label(); - masm.movq(AMD64.rdx, java.lang.Long.MIN_VALUE); - masm.cmpq(AMD64.rax, AMD64.rdx); - masm.jcc(ConditionFlag.notEqual, normalCase); - masm.cmpq(asRegister(src), -1); - masm.jcc(ConditionFlag.equal, continuation); - masm.bind(normalCase); - } - masm.cdqq(); exceptionOffset = masm.codeBuffer.position(); masm.idivq(asRegister(src)); - masm.bind(continuation); break; case IUDIV: diff -r 36dafe48bc38 -r 42b6e0905881 graal/com.oracle.graal.lir/src/com/oracle/graal/lir/LIRVerifier.java --- a/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/LIRVerifier.java Wed Jan 16 09:05:48 2013 +0100 +++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/LIRVerifier.java Wed Jan 16 09:08:24 2013 +0100 @@ -113,22 +113,6 @@ } assert lir.lir(block).get(0) instanceof StandardOp.LabelOp : "block must start with label"; - if (block.numberOfPreds() > 1) { - assert lir.lir(block).get(0) instanceof StandardOp.PhiLabelOp : "phi mapping required for multiple predecessors"; - Value[] phiDefinitions = ((StandardOp.PhiLabelOp) lir.lir(block).get(0)).getPhiDefinitions(); - if (!beforeRegisterAllocation) { - assert phiDefinitions.length == 0; - } - for (Block pred : block.getPredecessors()) { - assert pred.numberOfSux() == 1; - LIRInstruction last = lir.lir(pred).get(lir.lir(pred).size() - 1); - assert last instanceof StandardOp.PhiJumpOp : "phi mapping required for multiple successors"; - Value[] phiUses = ((StandardOp.PhiJumpOp) last).getPhiInputs(); - if (!beforeRegisterAllocation) { - assert phiUses.length == 0; - } - } - } if (block.numberOfSux() > 0) { LIRInstruction last = lir.lir(block).get(lir.lir(block).size() - 1); diff -r 36dafe48bc38 -r 42b6e0905881 graal/com.oracle.graal.lir/src/com/oracle/graal/lir/StandardOp.java --- a/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/StandardOp.java Wed Jan 16 09:05:48 2013 +0100 +++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/StandardOp.java Wed Jan 16 09:08:24 2013 +0100 @@ -60,7 +60,7 @@ @Override public void emitCode(TargetMethodAssembler tasm) { if (align) { - tasm.asm.align(tasm.target.wordSize); + tasm.asm.align(tasm.target.wordSize * 2); } tasm.asm.bind(label); } @@ -70,23 +70,6 @@ } } - public static class PhiLabelOp extends LabelOp { - @Def({REG, STACK}) protected Value[] phiDefinitions; - - public PhiLabelOp(Label label, boolean align, Value[] phiDefinitions) { - super(label, align); - this.phiDefinitions = phiDefinitions; - } - - public void markResolved() { - phiDefinitions = EMPTY; - } - - public Value[] getPhiDefinitions() { - return phiDefinitions; - } - } - /** * LIR operation that is an unconditional jump to {@link #destination()}. * When the LIR is constructed, the last operation of every block must implement this interface. After diff -r 36dafe48bc38 -r 42b6e0905881 graal/com.oracle.graal.loop/src/com/oracle/graal/loop/CountedLoopInfo.java --- a/graal/com.oracle.graal.loop/src/com/oracle/graal/loop/CountedLoopInfo.java Wed Jan 16 09:05:48 2013 +0100 +++ b/graal/com.oracle.graal.loop/src/com/oracle/graal/loop/CountedLoopInfo.java Wed Jan 16 09:08:24 2013 +0100 @@ -22,9 +22,9 @@ */ package com.oracle.graal.loop; -import com.oracle.graal.loop.InductionVariable.*; +import com.oracle.graal.graph.*; +import com.oracle.graal.loop.InductionVariable.Direction; import com.oracle.graal.nodes.*; -import com.oracle.graal.nodes.calc.*; public class CountedLoopInfo { private final LoopEx loop; @@ -41,7 +41,8 @@ public ValueNode maxTripCountNode() { //TODO (gd) stuarte and respect oneOff - return IntegerArithmeticNode.div(IntegerArithmeticNode.sub(end, iv.initNode()), iv.strideNode()); + throw GraalInternalError.unimplemented("division is a fixed node that needs to be inserted into the control flow"); + // return IntegerArithmeticNode.div(IntegerArithmeticNode.sub(end, iv.initNode()), iv.strideNode()); } public boolean isConstantMaxTripCount() { diff -r 36dafe48bc38 -r 42b6e0905881 graal/com.oracle.graal.loop/src/com/oracle/graal/loop/LoopTransformations.java --- a/graal/com.oracle.graal.loop/src/com/oracle/graal/loop/LoopTransformations.java Wed Jan 16 09:05:48 2013 +0100 +++ b/graal/com.oracle.graal.loop/src/com/oracle/graal/loop/LoopTransformations.java Wed Jan 16 09:08:24 2013 +0100 @@ -60,7 +60,7 @@ while (!loopBegin.isDeleted()) { int mark = graph.getMark(); peel(loop); - new CanonicalizerPhase(null, runtime, assumptions, mark).apply(graph); + new CanonicalizerPhase(null, runtime, assumptions, mark, null).apply(graph); if (iterations++ > UNROLL_LIMIT || graph.getNodeCount() > GraalOptions.MaximumDesiredSize * 3) { throw new BailoutException("FullUnroll : Graph seems to grow out of proportion"); } diff -r 36dafe48bc38 -r 42b6e0905881 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/FixedNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/FixedNode.java Wed Jan 16 09:05:48 2013 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/FixedNode.java Wed Jan 16 09:08:24 2013 +0100 @@ -41,6 +41,7 @@ } public void setProbability(double probability) { + assert probability >= 0 : String.format("Invalid argument %f, because the probability of a node must not be negative.", probability); this.probability = probability; assert !Double.isNaN(probability); } diff -r 36dafe48bc38 -r 42b6e0905881 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/IfNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/IfNode.java Wed Jan 16 09:05:48 2013 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/IfNode.java Wed Jan 16 09:08:24 2013 +0100 @@ -121,6 +121,10 @@ return this; } + public void setTakenProbability(double prob) { + takenProbability = prob; + } + @Override public double probability(BeginNode successor) { return successor == trueSuccessor ? takenProbability : 1 - takenProbability; @@ -358,10 +362,13 @@ PhiNode oldPhi = (PhiNode) oldMerge.usages().first(); PhiNode newPhi = graph().add(new PhiNode(oldPhi.stamp(), newMerge)); + double probability = 0.0; for (EndNode end : ends) { newPhi.addInput(phiValues.get(end)); newMerge.addForwardEnd(end); + probability += end.probability(); } + newMerge.setProbability(probability); FrameState stateAfter = oldMerge.stateAfter(); if (stateAfter != null) { @@ -425,6 +432,7 @@ originalFalseSuccessor.prepareDelete(); FixedNode next = merge.next(); + FrameState state = merge.stateAfter(); merge.setNext(null); setTrueSuccessor(null); setFalseSuccessor(null); @@ -435,6 +443,9 @@ merge.safeDelete(); trueEnd.safeDelete(); falseEnd.safeDelete(); + if (state != null) { + tool.removeIfUnused(state); + } tool.addToWorkList(next); } } diff -r 36dafe48bc38 -r 42b6e0905881 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/InvokeNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/InvokeNode.java Wed Jan 16 09:05:48 2013 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/InvokeNode.java Wed Jan 16 09:08:24 2013 +0100 @@ -109,6 +109,8 @@ Map debugProperties = super.getDebugProperties(map); if (callTarget instanceof MethodCallTargetNode && methodCallTarget().targetMethod() != null) { debugProperties.put("targetMethod", methodCallTarget().targetMethod()); + } else if (callTarget instanceof AbstractCallTargetNode) { + debugProperties.put("targetMethod", ((AbstractCallTargetNode) callTarget).target()); } return debugProperties; } diff -r 36dafe48bc38 -r 42b6e0905881 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/PiNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/PiNode.java Wed Jan 16 09:05:48 2013 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/PiNode.java Wed Jan 16 09:08:24 2013 +0100 @@ -59,7 +59,7 @@ @Override public boolean inferStamp() { if (object().objectStamp().alwaysNull() && objectStamp().nonNull()) { - // a null value flowing into a nonNull PiNode can happen should be guarded by a type/isNull guard, but the + // a null value flowing into a nonNull PiNode should be guarded by a type/isNull guard, but the // compiler might see this situation before the branch is deleted return false; } diff -r 36dafe48bc38 -r 42b6e0905881 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/FixedBinaryNode.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/FixedBinaryNode.java Wed Jan 16 09:08:24 2013 +0100 @@ -0,0 +1,49 @@ +/* + * 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.nodes.calc; + +import com.oracle.graal.api.meta.*; +import com.oracle.graal.graph.*; +import com.oracle.graal.nodes.*; +import com.oracle.graal.nodes.type.*; + +@NodeInfo(shortName = "/") +public class FixedBinaryNode extends FixedWithNextNode { + + @Input private ValueNode x; + @Input private ValueNode y; + + public ValueNode x() { + return x; + } + + public ValueNode y() { + return y; + } + + public FixedBinaryNode(Kind kind, ValueNode x, ValueNode y) { + super(StampFactory.forKind(kind)); + this.x = x; + this.y = y; + } +} diff -r 36dafe48bc38 -r 42b6e0905881 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IntegerArithmeticNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IntegerArithmeticNode.java Wed Jan 16 09:05:48 2013 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IntegerArithmeticNode.java Wed Jan 16 09:08:24 2013 +0100 @@ -72,17 +72,4 @@ throw ValueNodeUtil.shouldNotReachHere(); } } - - public static IntegerDivNode div(ValueNode v1, ValueNode v2) { - assert v1.kind() == v2.kind() && v1.graph() == v2.graph(); - Graph graph = v1.graph(); - switch(v1.kind()) { - case Int: - return graph.unique(new IntegerDivNode(Kind.Int, v1, v2)); - case Long: - return graph.unique(new IntegerDivNode(Kind.Long, v1, v2)); - default: - throw ValueNodeUtil.shouldNotReachHere(); - } - } } diff -r 36dafe48bc38 -r 42b6e0905881 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IntegerDivNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IntegerDivNode.java Wed Jan 16 09:05:48 2013 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IntegerDivNode.java Wed Jan 16 09:08:24 2013 +0100 @@ -30,7 +30,7 @@ import com.oracle.graal.nodes.type.*; @NodeInfo(shortName = "/") -public final class IntegerDivNode extends IntegerArithmeticNode implements Canonicalizable, LIRLowerable { +public class IntegerDivNode extends FixedBinaryNode implements Canonicalizable, Lowerable, LIRLowerable { public IntegerDivNode(Kind kind, ValueNode x, ValueNode y) { super(kind, x, y); @@ -87,10 +87,27 @@ return shift; } } + + // Convert the expression ((a - a % b) / b) into (a / b). + if (x() instanceof IntegerSubNode) { + IntegerSubNode integerSubNode = (IntegerSubNode) x(); + if (integerSubNode.y() instanceof IntegerRemNode) { + IntegerRemNode integerRemNode = (IntegerRemNode) integerSubNode.y(); + if (integerSubNode.kind() == this.kind() && integerRemNode.kind() == this.kind() && integerSubNode.x() == integerRemNode.x() && this.y() == integerRemNode.y()) { + return graph().add(new IntegerDivNode(kind(), integerSubNode.x(), this.y())); + } + } + } + return this; } @Override + public void lower(LoweringTool tool) { + tool.getRuntime().lower(this, tool); + } + + @Override public void generate(LIRGeneratorTool gen) { gen.setResult(this, gen.emitDiv(gen.operand(x()), gen.operand(y()))); } diff -r 36dafe48bc38 -r 42b6e0905881 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IntegerRemNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IntegerRemNode.java Wed Jan 16 09:05:48 2013 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IntegerRemNode.java Wed Jan 16 09:08:24 2013 +0100 @@ -29,7 +29,7 @@ import com.oracle.graal.nodes.spi.*; @NodeInfo(shortName = "%") -public final class IntegerRemNode extends IntegerArithmeticNode implements Canonicalizable, LIRLowerable { +public class IntegerRemNode extends FixedBinaryNode implements Canonicalizable, Lowerable, LIRLowerable { public IntegerRemNode(Kind kind, ValueNode x, ValueNode y) { super(kind, x, y); @@ -60,6 +60,11 @@ } @Override + public void lower(LoweringTool tool) { + tool.getRuntime().lower(this, tool); + } + + @Override public void generate(LIRGeneratorTool gen) { gen.setResult(this, gen.emitRem(gen.operand(x()), gen.operand(y()))); } diff -r 36dafe48bc38 -r 42b6e0905881 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/UnsignedDivNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/UnsignedDivNode.java Wed Jan 16 09:05:48 2013 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/UnsignedDivNode.java Wed Jan 16 09:08:24 2013 +0100 @@ -29,7 +29,7 @@ import com.oracle.graal.nodes.spi.*; @NodeInfo(shortName = "|/|") -public final class UnsignedDivNode extends IntegerArithmeticNode implements Canonicalizable, LIRLowerable { +public class UnsignedDivNode extends FixedBinaryNode implements Canonicalizable, Lowerable, LIRLowerable { public UnsignedDivNode(Kind kind, ValueNode x, ValueNode y) { super(kind, x, y); @@ -61,6 +61,11 @@ } @Override + public void lower(LoweringTool tool) { + tool.getRuntime().lower(this, tool); + } + + @Override public void generate(LIRGeneratorTool gen) { gen.setResult(this, gen.emitUDiv(gen.operand(x()), gen.operand(y()))); } diff -r 36dafe48bc38 -r 42b6e0905881 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/UnsignedRemNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/UnsignedRemNode.java Wed Jan 16 09:05:48 2013 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/UnsignedRemNode.java Wed Jan 16 09:08:24 2013 +0100 @@ -29,7 +29,7 @@ import com.oracle.graal.nodes.spi.*; @NodeInfo(shortName = "|%|") -public final class UnsignedRemNode extends IntegerArithmeticNode implements Canonicalizable, LIRLowerable { +public class UnsignedRemNode extends FixedBinaryNode implements Canonicalizable, Lowerable, LIRLowerable { public UnsignedRemNode(Kind kind, ValueNode x, ValueNode y) { super(kind, x, y); @@ -60,7 +60,12 @@ } @Override + public void lower(LoweringTool tool) { + tool.getRuntime().lower(this, tool); + } + + @Override public void generate(LIRGeneratorTool gen) { - gen.setResult(this, gen.emitRem(gen.operand(x()), gen.operand(y()))); + gen.setResult(this, gen.emitURem(gen.operand(x()), gen.operand(y()))); } } diff -r 36dafe48bc38 -r 42b6e0905881 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/cfg/Block.java diff -r 36dafe48bc38 -r 42b6e0905881 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/BoxNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/BoxNode.java Wed Jan 16 09:05:48 2013 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/BoxNode.java Wed Jan 16 09:08:24 2013 +0100 @@ -65,6 +65,33 @@ @Override public ValueNode canonical(CanonicalizerTool tool) { + + if (source.isConstant()) { + Constant sourceConstant = source.asConstant(); + switch (sourceKind) { + case Boolean: + return ConstantNode.forObject(Boolean.valueOf(sourceConstant.asBoolean()), tool.runtime(), graph()); + case Byte: + return ConstantNode.forObject(Byte.valueOf((byte) sourceConstant.asInt()), tool.runtime(), graph()); + case Char: + return ConstantNode.forObject(Character.valueOf((char) sourceConstant.asInt()), tool.runtime(), graph()); + case Short: + return ConstantNode.forObject(Short.valueOf((short) sourceConstant.asInt()), tool.runtime(), graph()); + case Int: + return ConstantNode.forObject(Integer.valueOf(sourceConstant.asInt()), tool.runtime(), graph()); + case Long: + return ConstantNode.forObject(Long.valueOf(sourceConstant.asLong()), tool.runtime(), graph()); + case Float: + return ConstantNode.forObject(Float.valueOf(sourceConstant.asFloat()), tool.runtime(), graph()); + case Double: + return ConstantNode.forObject(Double.valueOf(sourceConstant.asDouble()), tool.runtime(), graph()); + default: + assert false : "Unexpected source kind for boxing"; + break; + + } + } + for (Node usage : usages()) { if (usage != stateAfter()) { return this; diff -r 36dafe48bc38 -r 42b6e0905881 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/UnsafeCastNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/UnsafeCastNode.java Wed Jan 16 09:05:48 2013 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/UnsafeCastNode.java Wed Jan 16 09:08:24 2013 +0100 @@ -50,6 +50,19 @@ } @Override + public boolean inferStamp() { + if (kind() != Kind.Object || object().kind() != Kind.Object) { + return false; + } + if (object().objectStamp().alwaysNull() && objectStamp().nonNull()) { + // a null value flowing into a nonNull UnsafeCastNode should be guarded by a type/isNull guard, but the + // compiler might see this situation before the branch is deleted + return false; + } + return updateStamp(stamp().join(object().stamp())); + } + + @Override public ValueNode canonical(CanonicalizerTool tool) { if (kind() != object.kind()) { return this; diff -r 36dafe48bc38 -r 42b6e0905881 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/CheckCastNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/CheckCastNode.java Wed Jan 16 09:05:48 2013 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/CheckCastNode.java Wed Jan 16 09:08:24 2013 +0100 @@ -59,11 +59,10 @@ @Override public boolean inferStamp() { - if (object().stamp().nonNull() && !stamp().nonNull()) { - setStamp(StampFactory.declaredNonNull(type)); - return true; + if (object().objectStamp().alwaysNull() && objectStamp().nonNull()) { + return false; } - return super.inferStamp(); + return updateStamp(stamp().join(object().stamp())); } @Override diff -r 36dafe48bc38 -r 42b6e0905881 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/MethodCallTargetNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/MethodCallTargetNode.java Wed Jan 16 09:05:48 2013 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/MethodCallTargetNode.java Wed Jan 16 09:08:24 2013 +0100 @@ -148,4 +148,13 @@ } return targetMethod().getName(); } + + public static MethodCallTargetNode find(StructuredGraph graph, ResolvedJavaMethod method) { + for (MethodCallTargetNode target : graph.getNodes(MethodCallTargetNode.class)) { + if (target.targetMethod == method) { + return target; + } + } + return null; + } } diff -r 36dafe48bc38 -r 42b6e0905881 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/spi/CanonicalizerTool.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/spi/CanonicalizerTool.java Wed Jan 16 09:05:48 2013 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/spi/CanonicalizerTool.java Wed Jan 16 09:08:24 2013 +0100 @@ -24,10 +24,12 @@ import com.oracle.graal.api.code.*; import com.oracle.graal.api.meta.*; +import com.oracle.graal.graph.*; public interface CanonicalizerTool { TargetDescription target(); Assumptions assumptions(); MetaAccessProvider runtime(); + void removeIfUnused(Node node); } diff -r 36dafe48bc38 -r 42b6e0905881 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/type/ObjectStamp.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/type/ObjectStamp.java Wed Jan 16 09:05:48 2013 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/type/ObjectStamp.java Wed Jan 16 09:08:24 2013 +0100 @@ -128,7 +128,7 @@ } @Override - public Stamp join(Stamp otherStamp) { + public ObjectStamp join(Stamp otherStamp) { if (this == otherStamp) { return this; } diff -r 36dafe48bc38 -r 42b6e0905881 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/util/GraphUtil.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/util/GraphUtil.java Wed Jan 16 09:05:48 2013 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/util/GraphUtil.java Wed Jan 16 09:08:24 2013 +0100 @@ -186,30 +186,67 @@ /** * Gets an approximate source code location for a node if possible. * - * @return a file name and source line number in stack trace format (e.g. "String.java:32") - * if an approximate source location is found, null otherwise + * @return the StackTraceElements if an approximate source location is found, null otherwise */ - public static String approxSourceLocation(Node node) { + public static StackTraceElement[] approxSourceStackTraceElement(Node node) { + ArrayList elements = new ArrayList<>(); Node n = node; while (n != null) { if (n instanceof MethodCallTargetNode) { + elements.add(((MethodCallTargetNode) n).targetMethod().asStackTraceElement(-1)); n = ((MethodCallTargetNode) n).invoke().node(); } if (n instanceof StateSplit) { - FrameState stateAfter = ((StateSplit) n).stateAfter(); - if (stateAfter != null) { - ResolvedJavaMethod method = stateAfter.method(); + FrameState state = ((StateSplit) n).stateAfter(); + while (state != null) { + ResolvedJavaMethod method = state.method(); if (method != null) { - StackTraceElement stackTraceElement = method.asStackTraceElement(stateAfter.bci); - if (stackTraceElement.getFileName() != null && stackTraceElement.getLineNumber() >= 0) { - return stackTraceElement.getFileName() + ":" + stackTraceElement.getLineNumber(); - } + elements.add(method.asStackTraceElement(state.bci - 1)); } + state = state.outerFrameState(); } + break; } n = n.predecessor(); } + return elements.toArray(new StackTraceElement[elements.size()]); + } + + + /** + * Gets an approximate source code location for a node, encoded as an exception, if possible. + * + * @return the exception with the location + */ + public static RuntimeException approxSourceException(Node node, Throwable cause) { + final StackTraceElement[] elements = approxSourceStackTraceElement(node); + @SuppressWarnings("serial") + RuntimeException exception = new RuntimeException(cause.getMessage(), cause) { + + @Override + public synchronized Throwable fillInStackTrace() { + setStackTrace(elements); + return this; + } + }; + return exception; + } + + /** + * Gets an approximate source code location for a node if possible. + * + * @return a file name and source line number in stack trace format (e.g. "String.java:32") if an approximate source + * location is found, null otherwise + */ + public static String approxSourceLocation(Node node) { + StackTraceElement[] stackTraceElements = approxSourceStackTraceElement(node); + if (stackTraceElements != null && stackTraceElements.length > 0) { + StackTraceElement top = stackTraceElements[0]; + if (top.getFileName() != null && top.getLineNumber() >= 0) { + return top.getFileName() + ":" + top.getLineNumber(); + } + } return null; } diff -r 36dafe48bc38 -r 42b6e0905881 graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/CanonicalizerPhase.java --- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/CanonicalizerPhase.java Wed Jan 16 09:05:48 2013 +0100 +++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/CanonicalizerPhase.java Wed Jan 16 09:08:24 2013 +0100 @@ -50,14 +50,19 @@ private final TargetDescription target; private final Assumptions assumptions; private final MetaAccessProvider runtime; + private final CustomCanonicalizer customCanonicalizer; private final Iterable initWorkingSet; private NodeWorkList workList; private Tool tool; private List snapshotTemp; + public interface CustomCanonicalizer { + ValueNode canonicalize(Node node); + } + public CanonicalizerPhase(TargetDescription target, MetaAccessProvider runtime, Assumptions assumptions) { - this(target, runtime, assumptions, null, 0); + this(target, runtime, assumptions, null, 0, null); } /** @@ -65,24 +70,26 @@ * @param runtime * @param assumptions * @param workingSet the initial working set of nodes on which the canonicalizer works, should be an auto-grow node bitmap + * @param customCanonicalizer */ - public CanonicalizerPhase(TargetDescription target, MetaAccessProvider runtime, Assumptions assumptions, Iterable workingSet) { - this(target, runtime, assumptions, workingSet, 0); + public CanonicalizerPhase(TargetDescription target, MetaAccessProvider runtime, Assumptions assumptions, Iterable workingSet, CustomCanonicalizer customCanonicalizer) { + this(target, runtime, assumptions, workingSet, 0, customCanonicalizer); } /** * @param newNodesMark only the {@linkplain Graph#getNewNodes(int) new nodes} specified by * this mark are processed otherwise all nodes in the graph are processed */ - public CanonicalizerPhase(TargetDescription target, MetaAccessProvider runtime, Assumptions assumptions, int newNodesMark) { - this(target, runtime, assumptions, null, newNodesMark); + public CanonicalizerPhase(TargetDescription target, MetaAccessProvider runtime, Assumptions assumptions, int newNodesMark, CustomCanonicalizer customCanonicalizer) { + this(target, runtime, assumptions, null, newNodesMark, customCanonicalizer); } - public CanonicalizerPhase(TargetDescription target, MetaAccessProvider runtime, Assumptions assumptions, Iterable workingSet, int newNodesMark) { + public CanonicalizerPhase(TargetDescription target, MetaAccessProvider runtime, Assumptions assumptions, Iterable workingSet, int newNodesMark, CustomCanonicalizer customCanonicalizer) { this.newNodesMark = newNodesMark; this.target = target; this.assumptions = assumptions; this.runtime = runtime; + this.customCanonicalizer = customCanonicalizer; this.initWorkingSet = workingSet; this.snapshotTemp = new ArrayList<>(); } @@ -127,7 +134,7 @@ int mark = graph.getMark(); if (!tryKillUnused(node)) { node.inputs().filter(GraphUtil.isFloatingNode()).snapshotTo(snapshotTemp); - if (!tryCanonicalize(node, graph, tool)) { + if (!tryCanonicalize(node, graph)) { tryInferStamp(node, graph); } else { for (Node in : snapshotTemp) { @@ -168,7 +175,19 @@ return false; } - public static boolean tryCanonicalize(final Node node, final StructuredGraph graph, final SimplifierTool tool) { + public boolean tryCanonicalize(final Node node, final StructuredGraph graph) { + boolean result = baseTryCanonicalize(node, graph); + if (!result && customCanonicalizer != null) { + ValueNode canonical = customCanonicalizer.canonicalize(node); + if (canonical == node && customCanonicalizer != null) { + canonical = customCanonicalizer.canonicalize(node); + } + result = performReplacement(node, graph, canonical); + } + return result; + } + + public boolean baseTryCanonicalize(final Node node, final StructuredGraph graph) { if (node instanceof Canonicalizable) { assert !(node instanceof Simplifiable); METRIC_CANONICALIZATION_CONSIDERED_NODES.increment(); @@ -187,52 +206,9 @@ // Fixed-connected| 2 | X | 6 | // -------------------------------------------- // X: must not happen (checked with assertions) - if (canonical == node) { - Debug.log("Canonicalizer: work on %s", node); - return false; - } else { - Debug.log("Canonicalizer: replacing %s with %s", node, canonical); - METRIC_CANONICALIZED_NODES.increment(); - if (node instanceof FloatingNode) { - if (canonical == null) { - // case 1 - graph.removeFloating((FloatingNode) node); - } else { - // case 2 - assert !(canonical instanceof FixedNode) || (canonical.predecessor() != null || canonical instanceof StartNode || canonical instanceof MergeNode) : node + " -> " + canonical + - " : replacement should be floating or fixed and connected"; - graph.replaceFloating((FloatingNode) node, canonical); - } - } else { - assert node instanceof FixedWithNextNode && node.predecessor() != null : node + " -> " + canonical + " : node should be fixed & connected (" + node.predecessor() + ")"; - FixedWithNextNode fixedWithNext = (FixedWithNextNode) node; + - // When removing a fixed node, new canonicalization opportunities for its successor may arise - assert fixedWithNext.next() != null; - tool.addToWorkList(fixedWithNext.next()); - - if (canonical == null) { - // case 3 - graph.removeFixed(fixedWithNext); - } else if (canonical instanceof FloatingNode) { - // case 4 - graph.replaceFixedWithFloating(fixedWithNext, (FloatingNode) canonical); - } else { - assert canonical instanceof FixedNode; - if (canonical.predecessor() == null) { - assert !canonical.cfgSuccessors().iterator().hasNext() : "replacement " + canonical + " shouldn't have successors"; - // case 5 - graph.replaceFixedWithFixed(fixedWithNext, (FixedWithNextNode) canonical); - } else { - assert canonical.cfgSuccessors().iterator().hasNext() : "replacement " + canonical + " should have successors"; - // case 6 - node.replaceAtUsages(canonical); - graph.removeFixed(fixedWithNext); - } - } - } - return true; - } + return performReplacement(node, graph, canonical); } }); } else if (node instanceof Simplifiable) { @@ -247,6 +223,55 @@ return node.isDeleted(); } + private boolean performReplacement(final Node node, final StructuredGraph graph, ValueNode canonical) { + if (canonical == node) { + Debug.log("Canonicalizer: work on %s", node); + return false; + } else { + Debug.log("Canonicalizer: replacing %s with %s", node, canonical); + METRIC_CANONICALIZED_NODES.increment(); + if (node instanceof FloatingNode) { + if (canonical == null) { + // case 1 + graph.removeFloating((FloatingNode) node); + } else { + // case 2 + assert !(canonical instanceof FixedNode) || (canonical.predecessor() != null || canonical instanceof StartNode || canonical instanceof MergeNode) : node + " -> " + canonical + + " : replacement should be floating or fixed and connected"; + graph.replaceFloating((FloatingNode) node, canonical); + } + } else { + assert node instanceof FixedWithNextNode && node.predecessor() != null : node + " -> " + canonical + " : node should be fixed & connected (" + node.predecessor() + ")"; + FixedWithNextNode fixedWithNext = (FixedWithNextNode) node; + + // When removing a fixed node, new canonicalization opportunities for its successor may arise + assert fixedWithNext.next() != null; + tool.addToWorkList(fixedWithNext.next()); + + if (canonical == null) { + // case 3 + graph.removeFixed(fixedWithNext); + } else if (canonical instanceof FloatingNode) { + // case 4 + graph.replaceFixedWithFloating(fixedWithNext, (FloatingNode) canonical); + } else { + assert canonical instanceof FixedNode; + if (canonical.predecessor() == null) { + assert !canonical.cfgSuccessors().iterator().hasNext() : "replacement " + canonical + " shouldn't have successors"; + // case 5 + graph.replaceFixedWithFixed(fixedWithNext, (FixedWithNextNode) canonical); + } else { + assert canonical.cfgSuccessors().iterator().hasNext() : "replacement " + canonical + " should have successors"; + // case 6 + node.replaceAtUsages(canonical); + graph.removeFixed(fixedWithNext); + } + } + } + return true; + } + } + /** * Calls {@link ValueNode#inferStamp()} on the node and, if it returns true (which means that the stamp has * changed), re-queues the node's usages . If the stamp has changed then this method also checks if the stamp @@ -316,5 +341,10 @@ public void addToWorkList(Node node) { nodeWorkSet.addAgain(node); } + + @Override + public void removeIfUnused(Node node) { + tryKillUnused(node); + } } } diff -r 36dafe48bc38 -r 42b6e0905881 graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/ComputeProbabilityPhase.java --- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/ComputeProbabilityPhase.java Wed Jan 16 09:05:48 2013 +0100 +++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/ComputeProbabilityPhase.java Wed Jan 16 09:08:24 2013 +0100 @@ -72,6 +72,9 @@ private void correctLoopFrequencies(Loop loop, double parentFrequency, BitSet visitedBlocks) { LoopBeginNode loopBegin = ((LoopBeginNode) loop.header.getBeginNode()); double frequency = parentFrequency * loopBegin.loopFrequency(); + if (frequency < 1) { + frequency = 1; + } for (Loop child : loop.children) { correctLoopFrequencies(child, frequency, visitedBlocks); } diff -r 36dafe48bc38 -r 42b6e0905881 graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/InliningPhase.java --- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/InliningPhase.java Wed Jan 16 09:05:48 2013 +0100 +++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/InliningPhase.java Wed Jan 16 09:08:24 2013 +0100 @@ -32,11 +32,9 @@ import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.spi.*; import com.oracle.graal.phases.*; -import com.oracle.graal.phases.PhasePlan.PhasePosition; -import com.oracle.graal.phases.common.InliningUtil.InlineInfo; -import com.oracle.graal.phases.common.InliningUtil.InliningCallback; -import com.oracle.graal.phases.common.InliningUtil.InliningPolicy; -import com.oracle.graal.phases.common.InliningUtil.WeightComputationPolicy; +import com.oracle.graal.phases.PhasePlan.*; +import com.oracle.graal.phases.common.CanonicalizerPhase.CustomCanonicalizer; +import com.oracle.graal.phases.common.InliningUtil.*; public class InliningPhase extends Phase implements InliningCallback { /* @@ -52,6 +50,7 @@ private final Assumptions assumptions; private final GraphCache cache; private final InliningPolicy inliningPolicy; + private CustomCanonicalizer customCanonicalizer; // Metrics private static final DebugMetric metricInliningPerformed = Debug.metric("InliningPerformed"); @@ -63,6 +62,10 @@ this(target, runtime, assumptions, cache, plan, createInliningPolicy(assumptions, optimisticOpts, hints)); } + public void setCustomCanonicalizer(CustomCanonicalizer customCanonicalizer) { + this.customCanonicalizer = customCanonicalizer; + } + public InliningPhase(TargetDescription target, GraalCodeCacheProvider runtime, Assumptions assumptions, GraphCache cache, PhasePlan plan, InliningPolicy inliningPolicy) { this.target = target; this.runtime = runtime; @@ -91,7 +94,7 @@ Debug.dump(graph, "after %s", candidate); Iterable newNodes = graph.getNewNodes(mark); if (GraalOptions.OptCanonicalizer) { - new CanonicalizerPhase(target, runtime, assumptions, invokeUsages, mark).apply(graph); + new CanonicalizerPhase(target, runtime, assumptions, invokeUsages, mark, customCanonicalizer).apply(graph); } metricInliningPerformed.increment(); diff -r 36dafe48bc38 -r 42b6e0905881 graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/InliningUtil.java --- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/InliningUtil.java Wed Jan 16 09:05:48 2013 +0100 +++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/InliningUtil.java Wed Jan 16 09:08:24 2013 +0100 @@ -888,7 +888,7 @@ * @param inlineGraph the graph that the invoke will be replaced with * @param receiverNullCheck true if a null check needs to be generated for non-static inlinings, false if no such check is required */ - public static void inline(Invoke invoke, StructuredGraph inlineGraph, boolean receiverNullCheck) { + public static Map inline(Invoke invoke, StructuredGraph inlineGraph, boolean receiverNullCheck) { NodeInputList parameters = invoke.callTarget().arguments(); StructuredGraph graph = (StructuredGraph) invoke.node().graph(); @@ -917,7 +917,7 @@ } } } - replacements.put(entryPointNode, BeginNode.prevBegin(invoke.node())); // ensure proper anchoring of things that where anchored to the StartNode + replacements.put(entryPointNode, BeginNode.prevBegin(invoke.node())); // ensure proper anchoring of things that were anchored to the StartNode assert invoke.node().successors().first() != null : invoke; assert invoke.node().predecessor() != null; @@ -1028,6 +1028,8 @@ invoke.node().replaceAtUsages(null); GraphUtil.killCFG(invoke.node()); + + return duplicates; } public static void receiverNullCheck(Invoke invoke) { @@ -1041,7 +1043,8 @@ } public static boolean canIntrinsify(ResolvedJavaMethod target) { - return getIntrinsicGraph(target) != null; + StructuredGraph intrinsicGraph = getIntrinsicGraph(target); + return intrinsicGraph != null; } public static StructuredGraph getIntrinsicGraph(ResolvedJavaMethod target) { diff -r 36dafe48bc38 -r 42b6e0905881 graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/IterativeConditionalEliminationPhase.java --- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/IterativeConditionalEliminationPhase.java Wed Jan 16 09:05:48 2013 +0100 +++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/IterativeConditionalEliminationPhase.java Wed Jan 16 09:08:24 2013 +0100 @@ -55,7 +55,7 @@ if (canonicalizationRoots.isEmpty()) { break; } - new CanonicalizerPhase(target, runtime, assumptions, canonicalizationRoots).apply(graph); + new CanonicalizerPhase(target, runtime, assumptions, canonicalizationRoots, null).apply(graph); canonicalizationRoots.clear(); } } diff -r 36dafe48bc38 -r 42b6e0905881 graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/LoweringPhase.java --- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/LoweringPhase.java Wed Jan 16 09:05:48 2013 +0100 +++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/LoweringPhase.java Wed Jan 16 09:08:24 2013 +0100 @@ -132,7 +132,7 @@ deferred = false; processBlock(schedule.getCFG().getStartBlock(), graph.createNodeBitMap(), null, schedule, processed); Debug.dump(graph, "Lowering iteration %d", i++); - new CanonicalizerPhase(null, runtime, assumptions, mark).apply(graph); + new CanonicalizerPhase(null, runtime, assumptions, mark, null).apply(graph); if (!deferred && !containsLowerable(graph.getNewNodes(mark))) { // No new lowerable nodes - done! diff -r 36dafe48bc38 -r 42b6e0905881 graal/com.oracle.graal.phases/src/com/oracle/graal/phases/GraalOptions.java --- a/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/GraalOptions.java Wed Jan 16 09:05:48 2013 +0100 +++ b/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/GraalOptions.java Wed Jan 16 09:08:24 2013 +0100 @@ -123,6 +123,7 @@ // Debug settings: public static boolean Debug = true; + public static boolean DebugSnippets = false; public static boolean PerThreadDebugValues = ____; public static boolean SummarizeDebugValues = ____; public static boolean SummarizePerPhase = ____; @@ -210,6 +211,7 @@ public static boolean IntrinsifyThreadMethods = true; public static boolean IntrinsifyUnsafeMethods = true; public static boolean IntrinsifyMathMethods = true; + public static boolean IntrinsifyAESMethods = true; /** * Counts the various paths taken through snippets. diff -r 36dafe48bc38 -r 42b6e0905881 graal/com.oracle.graal.phases/src/com/oracle/graal/phases/util/GraphOrder.java --- a/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/util/GraphOrder.java Wed Jan 16 09:05:48 2013 +0100 +++ b/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/util/GraphOrder.java Wed Jan 16 09:08:24 2013 +0100 @@ -27,27 +27,13 @@ import com.oracle.graal.graph.*; import com.oracle.graal.nodes.*; -public class GraphOrder implements Iterable { +public final class GraphOrder implements Iterable { private final ArrayList nodes = new ArrayList<>(); private GraphOrder() { } - public GraphOrder(Graph graph) { - NodeBitMap visited = graph.createNodeBitMap(); - - for (ReturnNode node : graph.getNodes(ReturnNode.class)) { - visitForward(visited, node); - } - for (UnwindNode node : graph.getNodes(UnwindNode.class)) { - visitForward(visited, node); - } - for (DeoptimizeNode node : graph.getNodes(DeoptimizeNode.class)) { - visitForward(visited, node); - } - } - public static GraphOrder forwardGraph(Graph graph) { GraphOrder result = new GraphOrder(); @@ -92,6 +78,12 @@ for (Node input : node.inputs()) { visitForward(visited, input); } + if (node instanceof LoopBeginNode) { + LoopBeginNode loopBegin = (LoopBeginNode) node; + for (LoopEndNode loopEnd : loopBegin.loopEnds()) { + visitForward(visited, loopEnd); + } + } nodes.add(node); } } diff -r 36dafe48bc38 -r 42b6e0905881 graal/com.oracle.graal.printer/src/com/oracle/graal/printer/DebugEnvironment.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.printer/src/com/oracle/graal/printer/DebugEnvironment.java Wed Jan 16 09:08:24 2013 +0100 @@ -0,0 +1,48 @@ +/* + * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.graal.printer; + +import java.io.*; +import java.util.*; + +import com.oracle.graal.compiler.*; +import com.oracle.graal.debug.*; +import com.oracle.graal.phases.*; + + +public class DebugEnvironment { + + public static void initialize(PrintStream log) { + Debug.enable(); + List dumpHandlers = new ArrayList<>(); + dumpHandlers.add(new GraphPrinterDumpHandler()); + if (GraalOptions.PrintCFG) { + if (GraalOptions.PrintBinaryGraphs) { + TTY.println("CFG dumping slows down PrintBinaryGraphs: use -G:-PrintCFG to disable it"); + } + dumpHandlers.add(new CFGPrinterObserver()); + } + GraalDebugConfig hotspotDebugConfig = new GraalDebugConfig(GraalOptions.Log, GraalOptions.Meter, GraalOptions.Time, GraalOptions.Dump, GraalOptions.MethodFilter, log, dumpHandlers); + Debug.setConfig(hotspotDebugConfig); + } +} diff -r 36dafe48bc38 -r 42b6e0905881 graal/com.oracle.graal.snippets/src/com/oracle/graal/snippets/ClassSubstitution.java --- a/graal/com.oracle.graal.snippets/src/com/oracle/graal/snippets/ClassSubstitution.java Wed Jan 16 09:05:48 2013 +0100 +++ b/graal/com.oracle.graal.snippets/src/com/oracle/graal/snippets/ClassSubstitution.java Wed Jan 16 09:08:24 2013 +0100 @@ -24,31 +24,61 @@ import java.lang.annotation.*; +import com.oracle.graal.api.meta.*; + /** - * Denotes a class that substitutes methods of another specified class with snippets. + * Denotes a class that substitutes methods of another specified class. + * The substitute methods are exactly those annotated by {@link MethodSubstitution}. */ @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.TYPE) public @interface ClassSubstitution { - Class value(); + /** + * Specifies the original class. + *

+ * If the default value is specified for this element, then a non-default + * value must be given for the {@link #className()} element. + */ + Class value() default ClassSubstitution.class; /** - * Used to map a substitute method to an original method where the default mapping - * of name and signature is not possible due to name clashes with final methods in - * {@link Object} or signature types that are not public. + * Specifies the original class. + *

+ * This method is provided for cases where the original class + * is not accessible (according to Java language access control rules). + *

+ * If the default value is specified for this element, then a non-default + * value must be given for the {@link #value()} element. + */ + String className() default ""; + + /** + * Denotes a substitute method. A substitute method can call the original/substituted + * method by making a recursive call to itself. */ @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.METHOD) public @interface MethodSubstitution { /** - * Get the name of the original method. + * Gets the name of the original method. + *

+ * If the default value is specified for this element, then the + * name of the original method is same as the substitute method. */ String value() default ""; /** - * Determine if the substituted method is static. + * Determines if the original method is static. */ boolean isStatic() default true; + + /** + * Gets the {@linkplain Signature#getMethodDescriptor() signature} of the original method. + *

+ * If the default value is specified for this element, then the + * signature of the original method is the same as the substitute method. + */ + String signature() default ""; } } diff -r 36dafe48bc38 -r 42b6e0905881 graal/com.oracle.graal.snippets/src/com/oracle/graal/snippets/DoubleSnippets.java --- a/graal/com.oracle.graal.snippets/src/com/oracle/graal/snippets/DoubleSnippets.java Wed Jan 16 09:05:48 2013 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,55 +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.snippets; - -import com.oracle.graal.nodes.calc.*; - -/** - * Snippets for {@link java.lang.Double} methods. - */ -@ClassSubstitution(java.lang.Double.class) -public class DoubleSnippets implements SnippetsInterface { - - private static final long NAN_RAW_LONG_BITS = Double.doubleToRawLongBits(Double.NaN); - - public static long doubleToRawLongBits(double value) { - @JavacBug(id = 6995200) - Long result = ConvertNode.convert(ConvertNode.Op.MOV_D2L, value); - return result; - } - - // TODO This method is not necessary, since the JDK method does exactly this - public static long doubleToLongBits(double value) { - if (value != value) { - return NAN_RAW_LONG_BITS; - } else { - return doubleToRawLongBits(value); - } - } - - public static double longBitsToDouble(long bits) { - @JavacBug(id = 6995200) - Double result = ConvertNode.convert(ConvertNode.Op.MOV_L2D, bits); - return result; - } -} diff -r 36dafe48bc38 -r 42b6e0905881 graal/com.oracle.graal.snippets/src/com/oracle/graal/snippets/DoubleSubstitutions.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.snippets/src/com/oracle/graal/snippets/DoubleSubstitutions.java Wed Jan 16 09:08:24 2013 +0100 @@ -0,0 +1,59 @@ +/* + * 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.nodes.calc.*; +import com.oracle.graal.snippets.ClassSubstitution.*; + +/** + * Substitutions for {@link java.lang.Double} methods. + */ +@ClassSubstitution(java.lang.Double.class) +public class DoubleSubstitutions { + + private static final long NAN_RAW_LONG_BITS = Double.doubleToRawLongBits(Double.NaN); + + @MethodSubstitution + public static long doubleToRawLongBits(double value) { + @JavacBug(id = 6995200) + Long result = ConvertNode.convert(ConvertNode.Op.MOV_D2L, value); + return result; + } + + // TODO This method is not necessary, since the JDK method does exactly this + @MethodSubstitution + public static long doubleToLongBits(double value) { + if (value != value) { + return NAN_RAW_LONG_BITS; + } else { + return doubleToRawLongBits(value); + } + } + + @MethodSubstitution + public static double longBitsToDouble(long bits) { + @JavacBug(id = 6995200) + Double result = ConvertNode.convert(ConvertNode.Op.MOV_L2D, bits); + return result; + } +} diff -r 36dafe48bc38 -r 42b6e0905881 graal/com.oracle.graal.snippets/src/com/oracle/graal/snippets/FloatSnippets.java --- a/graal/com.oracle.graal.snippets/src/com/oracle/graal/snippets/FloatSnippets.java Wed Jan 16 09:05:48 2013 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,55 +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.snippets; - -import com.oracle.graal.nodes.calc.*; - -/** - * Snippets for {@link java.lang.Float} methods. - */ -@ClassSubstitution(java.lang.Float.class) -public class FloatSnippets implements SnippetsInterface { - - private static final int NAN_RAW_INT_BITS = Float.floatToRawIntBits(Float.NaN); - - public static int floatToRawIntBits(float value) { - @JavacBug(id = 6995200) - Integer result = ConvertNode.convert(ConvertNode.Op.MOV_F2I, value); - return result; - } - - // TODO This method is not necessary, since the JDK method does exactly this - public static int floatToIntBits(float value) { - if (value != value) { - return NAN_RAW_INT_BITS; - } else { - return floatToRawIntBits(value); - } - } - - public static float intBitsToFloat(int bits) { - @JavacBug(id = 6995200) - Float result = ConvertNode.convert(ConvertNode.Op.MOV_I2F, bits); - return result; - } -} diff -r 36dafe48bc38 -r 42b6e0905881 graal/com.oracle.graal.snippets/src/com/oracle/graal/snippets/FloatSubstitutions.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.snippets/src/com/oracle/graal/snippets/FloatSubstitutions.java Wed Jan 16 09:08:24 2013 +0100 @@ -0,0 +1,59 @@ +/* + * 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.nodes.calc.*; +import com.oracle.graal.snippets.ClassSubstitution.*; + +/** + * Substitutions for {@link java.lang.Float} methods. + */ +@ClassSubstitution(java.lang.Float.class) +public class FloatSubstitutions { + + private static final int NAN_RAW_INT_BITS = Float.floatToRawIntBits(Float.NaN); + + @MethodSubstitution + public static int floatToRawIntBits(float value) { + @JavacBug(id = 6995200) + Integer result = ConvertNode.convert(ConvertNode.Op.MOV_F2I, value); + return result; + } + + // TODO This method is not necessary, since the JDK method does exactly this + @MethodSubstitution + public static int floatToIntBits(float value) { + if (value != value) { + return NAN_RAW_INT_BITS; + } else { + return floatToRawIntBits(value); + } + } + + @MethodSubstitution + public static float intBitsToFloat(int bits) { + @JavacBug(id = 6995200) + Float result = ConvertNode.convert(ConvertNode.Op.MOV_I2F, bits); + return result; + } +} diff -r 36dafe48bc38 -r 42b6e0905881 graal/com.oracle.graal.snippets/src/com/oracle/graal/snippets/GraalIntrinsics.java --- a/graal/com.oracle.graal.snippets/src/com/oracle/graal/snippets/GraalIntrinsics.java Wed Jan 16 09:05:48 2013 +0100 +++ b/graal/com.oracle.graal.snippets/src/com/oracle/graal/snippets/GraalIntrinsics.java Wed Jan 16 09:08:24 2013 +0100 @@ -30,13 +30,13 @@ public class GraalIntrinsics { public static void installIntrinsics(SnippetInstaller installer) { if (GraalOptions.Intrinsify) { - installer.install(MathSnippetsX86.class); - installer.install(DoubleSnippets.class); - installer.install(FloatSnippets.class); - installer.install(NodeClassSnippets.class); - installer.install(LongSnippets.class); - installer.install(IntegerSnippets.class); - installer.install(UnsignedMathSnippets.class); + installer.installSubstitutions(MathSubstitutionsX86.class); + installer.installSubstitutions(DoubleSubstitutions.class); + installer.installSubstitutions(FloatSubstitutions.class); + installer.installSubstitutions(NodeClassSubstitutions.class); + installer.installSubstitutions(LongSubstitutions.class); + installer.installSubstitutions(IntegerSubstitutions.class); + installer.installSubstitutions(UnsignedMathSubstitutions.class); } } } diff -r 36dafe48bc38 -r 42b6e0905881 graal/com.oracle.graal.snippets/src/com/oracle/graal/snippets/IntegerSnippets.java --- a/graal/com.oracle.graal.snippets/src/com/oracle/graal/snippets/IntegerSnippets.java Wed Jan 16 09:05:48 2013 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,51 +0,0 @@ -/* - * Copyright (c) 2012, 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; - -import com.oracle.graal.snippets.nodes.*; - -@ClassSubstitution(Integer.class) -public class IntegerSnippets implements SnippetsInterface{ - - public static int reverseBytes(int i) { - return ReverseBytesNode.reverse(i); - } - - public static int numberOfLeadingZeros(int i) { - if (i == 0) { - return 32; - } - return 31 - BitScanReverseNode.scan(i); - } - - public static int numberOfTrailingZeros(int i) { - if (i == 0) { - return 32; - } - return BitScanForwardNode.scan(i); - } - - public static int bitCount(int i) { - return BitCountNode.bitCount(i); - } -} diff -r 36dafe48bc38 -r 42b6e0905881 graal/com.oracle.graal.snippets/src/com/oracle/graal/snippets/IntegerSubstitutions.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.snippets/src/com/oracle/graal/snippets/IntegerSubstitutions.java Wed Jan 16 09:08:24 2013 +0100 @@ -0,0 +1,56 @@ +/* + * Copyright (c) 2012, 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; + +import com.oracle.graal.snippets.ClassSubstitution.*; +import com.oracle.graal.snippets.nodes.*; + +@ClassSubstitution(Integer.class) +public class IntegerSubstitutions { + + @MethodSubstitution + public static int reverseBytes(int i) { + return ReverseBytesNode.reverse(i); + } + + @MethodSubstitution + public static int numberOfLeadingZeros(int i) { + if (i == 0) { + return 32; + } + return 31 - BitScanReverseNode.scan(i); + } + + @MethodSubstitution + public static int numberOfTrailingZeros(int i) { + if (i == 0) { + return 32; + } + return BitScanForwardNode.scan(i); + } + + @MethodSubstitution + public static int bitCount(int i) { + return BitCountNode.bitCount(i); + } +} diff -r 36dafe48bc38 -r 42b6e0905881 graal/com.oracle.graal.snippets/src/com/oracle/graal/snippets/LongSnippets.java --- a/graal/com.oracle.graal.snippets/src/com/oracle/graal/snippets/LongSnippets.java Wed Jan 16 09:05:48 2013 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,51 +0,0 @@ -/* - * Copyright (c) 2012, 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; - -import com.oracle.graal.snippets.nodes.*; - -@ClassSubstitution(Long.class) -public class LongSnippets implements SnippetsInterface{ - - public static long reverseBytes(long i) { - return ReverseBytesNode.reverse(i); - } - - public static int numberOfLeadingZeros(long i) { - if (i == 0) { - return 64; - } - return 63 - BitScanReverseNode.scan(i); - } - - public static int numberOfTrailingZeros(long i) { - if (i == 0) { - return 64; - } - return BitScanForwardNode.scan(i); - } - - public static int bitCount(long i) { - return BitCountNode.bitCount(i); - } -} diff -r 36dafe48bc38 -r 42b6e0905881 graal/com.oracle.graal.snippets/src/com/oracle/graal/snippets/LongSubstitutions.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.snippets/src/com/oracle/graal/snippets/LongSubstitutions.java Wed Jan 16 09:08:24 2013 +0100 @@ -0,0 +1,56 @@ +/* + * Copyright (c) 2012, 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; + +import com.oracle.graal.snippets.ClassSubstitution.*; +import com.oracle.graal.snippets.nodes.*; + +@ClassSubstitution(Long.class) +public class LongSubstitutions { + + @MethodSubstitution + public static long reverseBytes(long i) { + return ReverseBytesNode.reverse(i); + } + + @MethodSubstitution + public static int numberOfLeadingZeros(long i) { + if (i == 0) { + return 64; + } + return 63 - BitScanReverseNode.scan(i); + } + + @MethodSubstitution + public static int numberOfTrailingZeros(long i) { + if (i == 0) { + return 64; + } + return BitScanForwardNode.scan(i); + } + + @MethodSubstitution + public static int bitCount(long i) { + return BitCountNode.bitCount(i); + } +} diff -r 36dafe48bc38 -r 42b6e0905881 graal/com.oracle.graal.snippets/src/com/oracle/graal/snippets/MathSnippetsX86.java --- a/graal/com.oracle.graal.snippets/src/com/oracle/graal/snippets/MathSnippetsX86.java Wed Jan 16 09:05:48 2013 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,92 +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.snippets; - -import com.oracle.graal.api.code.RuntimeCallTarget.Descriptor; -import com.oracle.graal.graph.Node.ConstantNodeParameter; -import com.oracle.graal.graph.Node.NodeIntrinsic; -import com.oracle.graal.nodes.extended.*; -import com.oracle.graal.snippets.nodes.*; -import com.oracle.graal.snippets.nodes.MathIntrinsicNode.Operation; - -/** - * Snippets for {@link java.lang.Math} methods. - */ -@ClassSubstitution(java.lang.Math.class) -public class MathSnippetsX86 implements SnippetsInterface { - - private static final double PI_4 = 0.7853981633974483; - - public static double abs(double x) { - return MathIntrinsicNode.compute(x, Operation.ABS); - } - - public static double sqrt(double x) { - return MathIntrinsicNode.compute(x, Operation.SQRT); - } - - public static double log(double x) { - return MathIntrinsicNode.compute(x, Operation.LOG); - } - - public static double log10(double x) { - return MathIntrinsicNode.compute(x, Operation.LOG10); - } - - // NOTE on snippets below: - // Math.sin(), .cos() and .tan() guarantee a value within 1 ULP of the - // exact result, but x87 trigonometric FPU instructions are only that - // accurate within [-pi/4, pi/4]. Examine the passed value and provide - // a slow path for inputs outside of that interval. - - public static double sin(double x) { - if (abs(x) < PI_4) { - return MathIntrinsicNode.compute(x, Operation.SIN); - } else { - return callDouble(ARITHMETIC_SIN, x); - } - } - - public static double cos(double x) { - if (abs(x) < PI_4) { - return MathIntrinsicNode.compute(x, Operation.COS); - } else { - return callDouble(ARITHMETIC_COS, x); - } - } - - public static double tan(double x) { - if (abs(x) < PI_4) { - return MathIntrinsicNode.compute(x, Operation.TAN); - } else { - return callDouble(ARITHMETIC_TAN, x); - } - } - - public static final Descriptor ARITHMETIC_SIN = new Descriptor("arithmeticSin", false, double.class, double.class); - public static final Descriptor ARITHMETIC_COS = new Descriptor("arithmeticCos", false, double.class, double.class); - public static final Descriptor ARITHMETIC_TAN = new Descriptor("arithmeticTan", false, double.class, double.class); - - @NodeIntrinsic(value = RuntimeCallNode.class, setStampFromReturnType = true) - public static native double callDouble(@ConstantNodeParameter Descriptor descriptor, double value); -} diff -r 36dafe48bc38 -r 42b6e0905881 graal/com.oracle.graal.snippets/src/com/oracle/graal/snippets/MathSubstitutionsX86.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.snippets/src/com/oracle/graal/snippets/MathSubstitutionsX86.java Wed Jan 16 09:08:24 2013 +0100 @@ -0,0 +1,100 @@ +/* + * 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.code.RuntimeCallTarget.Descriptor; +import com.oracle.graal.graph.Node.ConstantNodeParameter; +import com.oracle.graal.graph.Node.NodeIntrinsic; +import com.oracle.graal.nodes.extended.*; +import com.oracle.graal.snippets.ClassSubstitution.MethodSubstitution; +import com.oracle.graal.snippets.nodes.*; +import com.oracle.graal.snippets.nodes.MathIntrinsicNode.Operation; + +/** + * Substitutions for {@link java.lang.Math} methods. + */ +@ClassSubstitution(java.lang.Math.class) +public class MathSubstitutionsX86 { + + private static final double PI_4 = 0.7853981633974483; + + @MethodSubstitution + public static double abs(double x) { + return MathIntrinsicNode.compute(x, Operation.ABS); + } + + @MethodSubstitution + public static double sqrt(double x) { + return MathIntrinsicNode.compute(x, Operation.SQRT); + } + + @MethodSubstitution + public static double log(double x) { + return MathIntrinsicNode.compute(x, Operation.LOG); + } + + @MethodSubstitution + public static double log10(double x) { + return MathIntrinsicNode.compute(x, Operation.LOG10); + } + + // NOTE on snippets below: + // Math.sin(), .cos() and .tan() guarantee a value within 1 ULP of the + // exact result, but x87 trigonometric FPU instructions are only that + // accurate within [-pi/4, pi/4]. Examine the passed value and provide + // a slow path for inputs outside of that interval. + + @MethodSubstitution + public static double sin(double x) { + if (abs(x) < PI_4) { + return MathIntrinsicNode.compute(x, Operation.SIN); + } else { + return callDouble(ARITHMETIC_SIN, x); + } + } + + @MethodSubstitution + public static double cos(double x) { + if (abs(x) < PI_4) { + return MathIntrinsicNode.compute(x, Operation.COS); + } else { + return callDouble(ARITHMETIC_COS, x); + } + } + + @MethodSubstitution + public static double tan(double x) { + if (abs(x) < PI_4) { + return MathIntrinsicNode.compute(x, Operation.TAN); + } else { + return callDouble(ARITHMETIC_TAN, x); + } + } + + public static final Descriptor ARITHMETIC_SIN = new Descriptor("arithmeticSin", false, double.class, double.class); + public static final Descriptor ARITHMETIC_COS = new Descriptor("arithmeticCos", false, double.class, double.class); + public static final Descriptor ARITHMETIC_TAN = new Descriptor("arithmeticTan", false, double.class, double.class); + + @NodeIntrinsic(value = RuntimeCallNode.class, setStampFromReturnType = true) + public static native double callDouble(@ConstantNodeParameter Descriptor descriptor, double value); +} diff -r 36dafe48bc38 -r 42b6e0905881 graal/com.oracle.graal.snippets/src/com/oracle/graal/snippets/NodeClassSnippets.java --- a/graal/com.oracle.graal.snippets/src/com/oracle/graal/snippets/NodeClassSnippets.java Wed Jan 16 09:05:48 2013 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,56 +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.snippets; - -import com.oracle.graal.api.meta.*; -import com.oracle.graal.graph.*; -import com.oracle.graal.nodes.extended.*; - -/** - * Snippets for improving the performance of some critical methods in {@link NodeClass} methods. - * These snippets improve the performance by forcing the relevant methods to be inlined - * (intrinsification being a special form of inlining) and removing a checked cast. - * The latter cannot be done directly in Java code as {@link UnsafeCastNode} - * is not available to the project containing {@link NodeClass}. - */ -@SuppressWarnings("unused") -@ClassSubstitution(NodeClass.class) -public class NodeClassSnippets implements SnippetsInterface { - - private static Node getNode(Node node, long offset) { - return UnsafeCastNode.unsafeCast(UnsafeLoadNode.load(node, 0, offset, Kind.Object), Node.class, false, false); - } - - private static NodeList getNodeList(Node node, long offset) { - return UnsafeCastNode.unsafeCast(UnsafeLoadNode.load(node, 0, offset, Kind.Object), NodeList.class, false, false); - } - - private static void putNode(Node node, long offset, Node value) { - UnsafeStoreNode.store(node, 0, offset, value, Kind.Object); - } - - private static void putNodeList(Node node, long offset, NodeList value) { - UnsafeStoreNode.store(node, 0, offset, value, Kind.Object); - } - -} diff -r 36dafe48bc38 -r 42b6e0905881 graal/com.oracle.graal.snippets/src/com/oracle/graal/snippets/NodeClassSubstitutions.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.snippets/src/com/oracle/graal/snippets/NodeClassSubstitutions.java Wed Jan 16 09:08:24 2013 +0100 @@ -0,0 +1,60 @@ +/* + * 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.graph.*; +import com.oracle.graal.nodes.extended.*; +import com.oracle.graal.snippets.ClassSubstitution.*; + +/** + * Substitutions for improving the performance of some critical methods in {@link NodeClass} methods. + * These substitutions improve the performance by forcing the relevant methods to be inlined + * (intrinsification being a special form of inlining) and removing a checked cast. + * The latter cannot be done directly in Java code as {@link UnsafeCastNode} + * is not available to the project containing {@link NodeClass}. + */ +@ClassSubstitution(NodeClass.class) +public class NodeClassSubstitutions { + + @MethodSubstitution + private static Node getNode(Node node, long offset) { + return UnsafeCastNode.unsafeCast(UnsafeLoadNode.load(node, 0, offset, Kind.Object), Node.class, false, false); + } + + @MethodSubstitution + private static NodeList getNodeList(Node node, long offset) { + return UnsafeCastNode.unsafeCast(UnsafeLoadNode.load(node, 0, offset, Kind.Object), NodeList.class, false, false); + } + + @MethodSubstitution + private static void putNode(Node node, long offset, Node value) { + UnsafeStoreNode.store(node, 0, offset, value, Kind.Object); + } + + @MethodSubstitution + private static void putNodeList(Node node, long offset, NodeList value) { + UnsafeStoreNode.store(node, 0, offset, value, Kind.Object); + } + +} diff -r 36dafe48bc38 -r 42b6e0905881 graal/com.oracle.graal.snippets/src/com/oracle/graal/snippets/SnippetInstaller.java --- a/graal/com.oracle.graal.snippets/src/com/oracle/graal/snippets/SnippetInstaller.java Wed Jan 16 09:05:48 2013 +0100 +++ b/graal/com.oracle.graal.snippets/src/com/oracle/graal/snippets/SnippetInstaller.java Wed Jan 16 09:08:24 2013 +0100 @@ -22,15 +22,18 @@ */ package com.oracle.graal.snippets; +import static com.oracle.graal.api.meta.MetaUtil.*; + import java.lang.reflect.*; import java.util.*; import java.util.concurrent.*; +import sun.misc.*; + 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.graph.Node.NodeIntrinsic; import com.oracle.graal.java.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.extended.*; @@ -44,7 +47,8 @@ import com.oracle.graal.word.phases.*; /** - * Utility for snippet {@linkplain #install(Class) installation}. + * Utility for {@linkplain #installSnippets(Class) snippet} and + * {@linkplain #installSubstitutions(Class) substitution} installation. */ public class SnippetInstaller { @@ -52,6 +56,7 @@ private final TargetDescription target; private final Assumptions assumptions; private final BoxingMethodPool pool; + private final Thread owner; /** * A graph cache used by this installer to avoid using the compiler @@ -67,26 +72,15 @@ this.assumptions = assumptions; this.pool = new BoxingMethodPool(runtime); this.graphCache = new HashMap<>(); + this.owner = Thread.currentThread(); } /** * Finds all the snippet methods in a given class, builds a graph for them and * installs the graph with the key value of {@code Graph.class} in the * {@linkplain ResolvedJavaMethod#getCompilerStorage() compiler storage} of each method. - *

- * If {@code snippetsHolder} is annotated with {@link ClassSubstitution}, then all - * methods in the class are snippets. Otherwise, the snippets are those methods - * annotated with {@link Snippet}. */ - public void install(Class snippetsHolder) { - if (snippetsHolder.isAnnotationPresent(ClassSubstitution.class)) { - installSubstitutions(snippetsHolder, snippetsHolder.getAnnotation(ClassSubstitution.class).value()); - } else { - installSnippets(snippetsHolder); - } - } - - private void installSnippets(Class< ? extends SnippetsInterface> clazz) { + public void installSnippets(Class< ? extends SnippetsInterface> clazz) { for (Method method : clazz.getDeclaredMethods()) { if (method.getAnnotation(Snippet.class) != null) { int modifiers = method.getModifiers(); @@ -102,43 +96,58 @@ } } - private void installSubstitutions(Class< ? extends SnippetsInterface> clazz, Class originalClazz) { - for (Method method : clazz.getDeclaredMethods()) { - if (method.getAnnotation(NodeIntrinsic.class) != null) { + /** + * Finds all the {@linkplain MethodSubstitution substitution} methods in a given class, + * builds a graph for them. If the original class is resolvable, then the + * graph is installed with the key value of {@code Graph.class} in the + * {@linkplain ResolvedJavaMethod#getCompilerStorage() compiler storage} of each original method. + */ + public void installSubstitutions(Class substitutions) { + assert owner == Thread.currentThread() : "substitution installation must be single threaded"; + ClassSubstitution classSubstitution = substitutions.getAnnotation(ClassSubstitution.class); + for (Method substituteMethod : substitutions.getDeclaredMethods()) { + MethodSubstitution methodSubstitution = substituteMethod.getAnnotation(MethodSubstitution.class); + if (methodSubstitution == null) { continue; } - try { - MethodSubstitution methodSubstitution = method.getAnnotation(MethodSubstitution.class); - String originalName = method.getName(); - Class[] originalParameters = method.getParameterTypes(); - if (methodSubstitution != null) { - if (!methodSubstitution.value().isEmpty()) { - originalName = methodSubstitution.value(); - } - if (!methodSubstitution.isStatic()) { - assert originalParameters.length >= 1 : "must be a static method with the this object as its first parameter"; - Class[] newParameters = new Class[originalParameters.length - 1]; - System.arraycopy(originalParameters, 1, newParameters, 0, newParameters.length); - originalParameters = newParameters; - } - } - Method originalMethod = originalClazz.getDeclaredMethod(originalName, originalParameters); - if (!originalMethod.getReturnType().isAssignableFrom(method.getReturnType())) { - throw new RuntimeException("Snippet has incompatible return type: " + method); - } - int modifiers = method.getModifiers(); - if (!Modifier.isStatic(modifiers)) { - throw new RuntimeException("Snippets must be static methods: " + method); - } else if (Modifier.isAbstract(modifiers) || Modifier.isNative(modifiers)) { - throw new RuntimeException("Snippet must not be abstract or native: " + method); - } - ResolvedJavaMethod snippet = runtime.lookupJavaMethod(method); - StructuredGraph graph = makeGraph(snippet, inliningPolicy(snippet), true); - //System.out.println("snippet: " + graph); - runtime.lookupJavaMethod(originalMethod).getCompilerStorage().put(Graph.class, graph); - } catch (NoSuchMethodException e) { - throw new GraalInternalError("Could not resolve method in " + originalClazz + " to substitute with " + method, e); + + int modifiers = substituteMethod.getModifiers(); + if (!Modifier.isStatic(modifiers)) { + throw new RuntimeException("Substitution methods must be static: " + substituteMethod); + } else if (Modifier.isAbstract(modifiers) || Modifier.isNative(modifiers)) { + throw new RuntimeException("Substitution method must not be abstract or native: " + substituteMethod); } + + String originalName = originalName(substituteMethod, methodSubstitution); + Class[] originalParameters = originalParameters(substituteMethod, methodSubstitution); + Method originalMethod = originalMethod(classSubstitution, originalName, originalParameters); + installSubstitution(originalMethod, substituteMethod); + } + } + + // These fields are used to detect calls from the substitute method to the original method. + ResolvedJavaMethod substitute; + ResolvedJavaMethod original; + boolean substituteCallsOriginal; + + /** + * Installs a method substitution. + * + * @param originalMethod a method being substituted + * @param substituteMethod the substitute method + */ + protected void installSubstitution(Method originalMethod, Method substituteMethod) { + substitute = runtime.lookupJavaMethod(substituteMethod); + original = runtime.lookupJavaMethod(originalMethod); + try { + //System.out.println("substitution: " + MetaUtil.format("%H.%n(%p)", original) + " --> " + MetaUtil.format("%H.%n(%p)", substitute)); + StructuredGraph graph = makeGraph(substitute, inliningPolicy(substitute), true); + Object oldValue = original.getCompilerStorage().put(Graph.class, graph); + assert oldValue == null; + } finally { + substitute = null; + original = null; + substituteCallsOriginal = false; } } @@ -158,7 +167,7 @@ } } - public StructuredGraph makeGraph(final ResolvedJavaMethod method, final SnippetInliningPolicy policy, final boolean isSubstitutionSnippet) { + public StructuredGraph makeGraph(final ResolvedJavaMethod method, final SnippetInliningPolicy policy, final boolean isSubstitution) { return Debug.scope("BuildSnippetGraph", new Object[] {method}, new Callable() { @Override public StructuredGraph call() throws Exception { @@ -166,8 +175,8 @@ new SnippetIntrinsificationPhase(runtime, pool, SnippetTemplate.hasConstantParameter(method)).apply(graph); - if (isSubstitutionSnippet) { - // TODO (ds) remove the constraint of only processing substitution snippets + if (isSubstitution && !substituteCallsOriginal) { + // TODO (ds) remove the constraint of only processing substitutions // once issues with the arraycopy snippets have been resolved new SnippetFrameStateCleanupPhase().apply(graph); new DeadCodeEliminationPhase().apply(graph); @@ -208,14 +217,29 @@ for (Invoke invoke : graph.getInvokes()) { MethodCallTargetNode callTarget = invoke.methodCallTarget(); ResolvedJavaMethod callee = callTarget.targetMethod(); - if ((callTarget.invokeKind() == InvokeKind.Static || callTarget.invokeKind() == InvokeKind.Special) && policy.shouldInline(callee, method)) { - StructuredGraph targetGraph = parseGraph(callee, policy); - InliningUtil.inline(invoke, targetGraph, true); + if (callee == substitute) { + final StructuredGraph originalGraph = new StructuredGraph(original); + new GraphBuilderPhase(runtime, GraphBuilderConfiguration.getSnippetDefault(), OptimisticOptimizations.NONE).apply(originalGraph); + InliningUtil.inline(invoke, originalGraph, true); + + // TODO the inlined frame states still show the call from the substitute to the original. + // If this poses a problem, a phase should added to fix up these frame states. + Debug.dump(graph, "after inlining %s", callee); if (GraalOptions.OptCanonicalizer) { - new WordTypeRewriterPhase(runtime, target.wordKind).apply(graph); new CanonicalizerPhase(target, runtime, assumptions).apply(graph); } + substituteCallsOriginal = true; + } else { + if ((callTarget.invokeKind() == InvokeKind.Static || callTarget.invokeKind() == InvokeKind.Special) && policy.shouldInline(callee, method)) { + StructuredGraph targetGraph = parseGraph(callee, policy); + InliningUtil.inline(invoke, targetGraph, true); + Debug.dump(graph, "after inlining %s", callee); + if (GraalOptions.OptCanonicalizer) { + new WordTypeRewriterPhase(runtime, target.wordKind).apply(graph); + new CanonicalizerPhase(target, runtime, assumptions).apply(graph); + } + } } } @@ -238,4 +262,65 @@ } return graph; } + + private static String originalName(Method substituteMethod, MethodSubstitution methodSubstitution) { + String name = substituteMethod.getName(); + if (!methodSubstitution.value().isEmpty()) { + name = methodSubstitution.value(); + } + return name; + } + + private static Class resolveType(String className) { + try { + // Need to use launcher class path to handle classes + // that are not on the boot class path + ClassLoader cl = Launcher.getLauncher().getClassLoader(); + return Class.forName(className, false, cl); + } catch (ClassNotFoundException e) { + throw new GraalInternalError("Could not resolve type " + className); + } + } + + private static Class resolveType(JavaType type) { + JavaType base = type; + int dimensions = 0; + while (base.getComponentType() != null) { + base = base.getComponentType(); + dimensions++; + } + + Class baseClass = base.getKind() != Kind.Object ? base.getKind().toJavaClass() : resolveType(toJavaName(base)); + return dimensions == 0 ? baseClass : Array.newInstance(baseClass, new int[dimensions]).getClass(); + } + + private Class[] originalParameters(Method substituteMethod, MethodSubstitution methodSubstitution) { + Class[] parameters; + if (methodSubstitution.signature().isEmpty()) { + parameters = substituteMethod.getParameterTypes(); + if (!methodSubstitution.isStatic()) { + assert parameters.length > 0 : "must be a static method with the 'this' object as its first parameter"; + parameters = Arrays.copyOfRange(parameters, 1, parameters.length); + } + } else { + Signature signature = runtime.parseMethodDescriptor(methodSubstitution.signature()); + parameters = new Class[signature.getParameterCount(false)]; + for (int i = 0; i < parameters.length; i++) { + parameters[i] = resolveType(signature.getParameterType(i, null)); + } + } + return parameters; + } + + private static Method originalMethod(ClassSubstitution classSubstitution, String name, Class[] parameters) { + Class originalClass = classSubstitution.value(); + if (originalClass == ClassSubstitution.class) { + originalClass = resolveType(classSubstitution.className()); + } + try { + return originalClass.getDeclaredMethod(name, parameters); + } catch (NoSuchMethodException | SecurityException e) { + throw new GraalInternalError(e); + } + } } diff -r 36dafe48bc38 -r 42b6e0905881 graal/com.oracle.graal.snippets/src/com/oracle/graal/snippets/SnippetTemplate.java --- a/graal/com.oracle.graal.snippets/src/com/oracle/graal/snippets/SnippetTemplate.java Wed Jan 16 09:05:48 2013 +0100 +++ b/graal/com.oracle.graal.snippets/src/com/oracle/graal/snippets/SnippetTemplate.java Wed Jan 16 09:08:24 2013 +0100 @@ -282,7 +282,7 @@ new SnippetIntrinsificationPhase(runtime, new BoxingMethodPool(runtime), false).apply(snippetCopy); new WordTypeRewriterPhase(runtime, target.wordKind).apply(snippetCopy); - new CanonicalizerPhase(null, runtime, assumptions, 0).apply(snippetCopy); + new CanonicalizerPhase(null, runtime, assumptions, 0, null).apply(snippetCopy); } // Gather the template parameters @@ -340,7 +340,7 @@ LoopEx loop = new LoopsData(snippetCopy).loop(loopBegin); int mark = snippetCopy.getMark(); LoopTransformations.fullUnroll(loop, runtime, null); - new CanonicalizerPhase(null, runtime, assumptions, mark).apply(snippetCopy); + new CanonicalizerPhase(null, runtime, assumptions, mark, null).apply(snippetCopy); } FixedNode explodeLoopNext = explodeLoop.next(); explodeLoop.clearSuccessors(); diff -r 36dafe48bc38 -r 42b6e0905881 graal/com.oracle.graal.snippets/src/com/oracle/graal/snippets/UnsafeSnippets.java --- a/graal/com.oracle.graal.snippets/src/com/oracle/graal/snippets/UnsafeSnippets.java Wed Jan 16 09:05:48 2013 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,382 +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.snippets; - -import com.oracle.graal.api.code.*; -import com.oracle.graal.api.meta.*; -import com.oracle.graal.nodes.extended.*; -import com.oracle.graal.nodes.java.*; -import com.oracle.graal.snippets.ClassSubstitution.MethodSubstitution; -import com.oracle.graal.snippets.nodes.*; - -/** - * Snippets for {@link sun.misc.Unsafe} methods. - */ -@ClassSubstitution(sun.misc.Unsafe.class) -public class UnsafeSnippets implements SnippetsInterface { - @MethodSubstitution(isStatic = false) - public static boolean compareAndSwapObject(@SuppressWarnings("unused") final Object thisObj, Object o, long offset, Object expected, Object x) { - return CompareAndSwapNode.compareAndSwap(o, 0, offset, expected, x); - } - - @MethodSubstitution(isStatic = false) - public static boolean compareAndSwapInt(@SuppressWarnings("unused") final Object thisObj, Object o, long offset, int expected, int x) { - return CompareAndSwapNode.compareAndSwap(o, 0, offset, expected, x); - } - - @MethodSubstitution(isStatic = false) - public static boolean compareAndSwapLong(@SuppressWarnings("unused") final Object thisObj, Object o, long offset, long expected, long x) { - return CompareAndSwapNode.compareAndSwap(o, 0, offset, expected, x); - } - - @MethodSubstitution(isStatic = false) - public static Object getObject(@SuppressWarnings("unused") final Object thisObj, Object o, long offset) { - return UnsafeLoadNode.load(o, 0, offset, Kind.Object); - } - - @MethodSubstitution(isStatic = false) - public static Object getObjectVolatile(final Object thisObj, Object o, long offset) { - MembarNode.memoryBarrier(MemoryBarriers.JMM_PRE_VOLATILE_READ); - Object result = getObject(thisObj, o, offset); - MembarNode.memoryBarrier(MemoryBarriers.JMM_POST_VOLATILE_READ); - return result; - } - - @MethodSubstitution(isStatic = false) - public static void putObject(@SuppressWarnings("unused") final Object thisObj, Object o, long offset, Object x) { - UnsafeStoreNode.store(o, 0, offset, x, Kind.Object); - } - - @MethodSubstitution(isStatic = false) - public static void putObjectVolatile(final Object thisObj, Object o, long offset, Object x) { - MembarNode.memoryBarrier(MemoryBarriers.JMM_PRE_VOLATILE_WRITE); - putObject(thisObj, o, offset, x); - MembarNode.memoryBarrier(MemoryBarriers.JMM_POST_VOLATILE_WRITE); - } - - @MethodSubstitution(isStatic = false) - public static void putOrderedObject(final Object thisObj, Object o, long offset, Object x) { - MembarNode.memoryBarrier(MemoryBarriers.JMM_PRE_VOLATILE_WRITE); - putObject(thisObj, o, offset, x); - MembarNode.memoryBarrier(MemoryBarriers.JMM_POST_VOLATILE_WRITE); - } - - @MethodSubstitution(isStatic = false) - public static int getInt(@SuppressWarnings("unused") final Object thisObj, Object o, long offset) { - Integer value = UnsafeLoadNode.load(o, 0, offset, Kind.Int); - return value; - } - - @MethodSubstitution(isStatic = false) - public static int getIntVolatile(final Object thisObj, Object o, long offset) { - MembarNode.memoryBarrier(MemoryBarriers.JMM_PRE_VOLATILE_READ); - int result = getInt(thisObj, o, offset); - MembarNode.memoryBarrier(MemoryBarriers.JMM_POST_VOLATILE_READ); - return result; - } - - @MethodSubstitution(isStatic = false) - public static void putInt(@SuppressWarnings("unused") final Object thisObj, Object o, long offset, int x) { - UnsafeStoreNode.store(o, 0, offset, x, Kind.Int); - } - - @MethodSubstitution(isStatic = false) - public static void putIntVolatile(final Object thisObj, Object o, long offset, int x) { - MembarNode.memoryBarrier(MemoryBarriers.JMM_PRE_VOLATILE_WRITE); - putInt(thisObj, o, offset, x); - MembarNode.memoryBarrier(MemoryBarriers.JMM_POST_VOLATILE_WRITE); - } - - @MethodSubstitution(isStatic = false) - public static void putOrderedInt(final Object thisObj, Object o, long offset, int x) { - MembarNode.memoryBarrier(MemoryBarriers.JMM_PRE_VOLATILE_WRITE); - putInt(thisObj, o, offset, x); - MembarNode.memoryBarrier(MemoryBarriers.JMM_POST_VOLATILE_WRITE); - } - - @MethodSubstitution(isStatic = false) - public static boolean getBoolean(@SuppressWarnings("unused") final Object thisObj, Object o, long offset) { - @JavacBug(id = 6995200) - Boolean result = UnsafeLoadNode.load(o, 0, offset, Kind.Boolean); - return result; - } - - @MethodSubstitution(isStatic = false) - public static boolean getBooleanVolatile(final Object thisObj, Object o, long offset) { - MembarNode.memoryBarrier(MemoryBarriers.JMM_PRE_VOLATILE_READ); - boolean result = getBoolean(thisObj, o, offset); - MembarNode.memoryBarrier(MemoryBarriers.JMM_POST_VOLATILE_READ); - return result; - } - - @MethodSubstitution(isStatic = false) - public static void putBoolean(@SuppressWarnings("unused") final Object thisObj, Object o, long offset, boolean x) { - UnsafeStoreNode.store(o, 0, offset, x, Kind.Boolean); - } - - @MethodSubstitution(isStatic = false) - public static void putBooleanVolatile(final Object thisObj, Object o, long offset, boolean x) { - MembarNode.memoryBarrier(MemoryBarriers.JMM_PRE_VOLATILE_WRITE); - putBoolean(thisObj, o, offset, x); - MembarNode.memoryBarrier(MemoryBarriers.JMM_POST_VOLATILE_WRITE); - } - - @MethodSubstitution(isStatic = false) - public static byte getByte(@SuppressWarnings("unused") final Object thisObj, Object o, long offset) { - @JavacBug(id = 6995200) - Byte result = UnsafeLoadNode.load(o, 0, offset, Kind.Byte); - return result; - } - - @MethodSubstitution(isStatic = false) - public static byte getByteVolatile(final Object thisObj, Object o, long offset) { - MembarNode.memoryBarrier(MemoryBarriers.JMM_PRE_VOLATILE_READ); - byte result = getByte(thisObj, o, offset); - MembarNode.memoryBarrier(MemoryBarriers.JMM_POST_VOLATILE_READ); - return result; - } - - @MethodSubstitution(isStatic = false) - public static void putByte(@SuppressWarnings("unused") final Object thisObj, Object o, long offset, byte x) { - UnsafeStoreNode.store(o, 0, offset, x, Kind.Byte); - } - - @MethodSubstitution(isStatic = false) - public static void putByteVolatile(final Object thisObj, Object o, long offset, byte x) { - MembarNode.memoryBarrier(MemoryBarriers.JMM_PRE_VOLATILE_WRITE); - putByte(thisObj, o, offset, x); - MembarNode.memoryBarrier(MemoryBarriers.JMM_POST_VOLATILE_WRITE); - } - - @MethodSubstitution(isStatic = false) - public static short getShort(@SuppressWarnings("unused") final Object thisObj, Object o, long offset) { - @JavacBug(id = 6995200) - Short result = UnsafeLoadNode.load(o, 0, offset, Kind.Short); - return result; - } - - @MethodSubstitution(isStatic = false) - public static short getShortVolatile(final Object thisObj, Object o, long offset) { - MembarNode.memoryBarrier(MemoryBarriers.JMM_PRE_VOLATILE_READ); - short result = getShort(thisObj, o, offset); - MembarNode.memoryBarrier(MemoryBarriers.JMM_POST_VOLATILE_READ); - return result; - } - - @MethodSubstitution(isStatic = false) - public static void putShort(@SuppressWarnings("unused") final Object thisObj, Object o, long offset, short x) { - UnsafeStoreNode.store(o, 0, offset, x, Kind.Short); - } - - @MethodSubstitution(isStatic = false) - public static void putShortVolatile(final Object thisObj, Object o, long offset, short x) { - MembarNode.memoryBarrier(MemoryBarriers.JMM_PRE_VOLATILE_WRITE); - putShort(thisObj, o, offset, x); - MembarNode.memoryBarrier(MemoryBarriers.JMM_POST_VOLATILE_WRITE); - } - - @MethodSubstitution(isStatic = false) - public static char getChar(@SuppressWarnings("unused") final Object thisObj, Object o, long offset) { - @JavacBug(id = 6995200) - Character result = UnsafeLoadNode.load(o, 0, offset, Kind.Char); - return result; - } - - @MethodSubstitution(isStatic = false) - public static char getCharVolatile(final Object thisObj, Object o, long offset) { - MembarNode.memoryBarrier(MemoryBarriers.JMM_PRE_VOLATILE_READ); - char result = getChar(thisObj, o, offset); - MembarNode.memoryBarrier(MemoryBarriers.JMM_POST_VOLATILE_READ); - return result; - } - - @MethodSubstitution(isStatic = false) - public static void putChar(@SuppressWarnings("unused") final Object thisObj, Object o, long offset, char x) { - UnsafeStoreNode.store(o, 0, offset, x, Kind.Char); - } - - @MethodSubstitution(isStatic = false) - public static void putCharVolatile(final Object thisObj, Object o, long offset, char x) { - MembarNode.memoryBarrier(MemoryBarriers.JMM_PRE_VOLATILE_WRITE); - putChar(thisObj, o, offset, x); - MembarNode.memoryBarrier(MemoryBarriers.JMM_POST_VOLATILE_WRITE); - } - - @MethodSubstitution(isStatic = false) - public static long getLong(@SuppressWarnings("unused") final Object thisObj, Object o, long offset) { - @JavacBug(id = 6995200) - Long result = UnsafeLoadNode.load(o, 0, offset, Kind.Long); - return result; - } - - @MethodSubstitution(isStatic = false) - public static long getLongVolatile(final Object thisObj, Object o, long offset) { - MembarNode.memoryBarrier(MemoryBarriers.JMM_PRE_VOLATILE_READ); - long result = getLong(thisObj, o, offset); - MembarNode.memoryBarrier(MemoryBarriers.JMM_POST_VOLATILE_READ); - return result; - } - - @MethodSubstitution(isStatic = false) - public static void putLong(@SuppressWarnings("unused") final Object thisObj, Object o, long offset, long x) { - UnsafeStoreNode.store(o, 0, offset, x, Kind.Long); - } - - @MethodSubstitution(isStatic = false) - public static void putLongVolatile(final Object thisObj, Object o, long offset, long x) { - MembarNode.memoryBarrier(MemoryBarriers.JMM_PRE_VOLATILE_WRITE); - putLong(thisObj, o, offset, x); - MembarNode.memoryBarrier(MemoryBarriers.JMM_POST_VOLATILE_WRITE); - } - - @MethodSubstitution(isStatic = false) - public static void putOrderedLong(final Object thisObj, Object o, long offset, long x) { - MembarNode.memoryBarrier(MemoryBarriers.JMM_PRE_VOLATILE_WRITE); - putLong(thisObj, o, offset, x); - MembarNode.memoryBarrier(MemoryBarriers.JMM_POST_VOLATILE_WRITE); - } - - @MethodSubstitution(isStatic = false) - public static float getFloat(@SuppressWarnings("unused") final Object thisObj, Object o, long offset) { - @JavacBug(id = 6995200) - Float result = UnsafeLoadNode.load(o, 0, offset, Kind.Float); - return result; - } - - @MethodSubstitution(isStatic = false) - public static float getFloatVolatile(final Object thisObj, Object o, long offset) { - MembarNode.memoryBarrier(MemoryBarriers.JMM_PRE_VOLATILE_READ); - float result = getFloat(thisObj, o, offset); - MembarNode.memoryBarrier(MemoryBarriers.JMM_POST_VOLATILE_READ); - return result; - } - - @MethodSubstitution(isStatic = false) - public static void putFloat(@SuppressWarnings("unused") final Object thisObj, Object o, long offset, float x) { - UnsafeStoreNode.store(o, 0, offset, x, Kind.Float); - } - - @MethodSubstitution(isStatic = false) - public static void putFloatVolatile(final Object thisObj, Object o, long offset, float x) { - MembarNode.memoryBarrier(MemoryBarriers.JMM_PRE_VOLATILE_WRITE); - putFloat(thisObj, o, offset, x); - MembarNode.memoryBarrier(MemoryBarriers.JMM_POST_VOLATILE_WRITE); - } - - @MethodSubstitution(isStatic = false) - public static double getDouble(@SuppressWarnings("unused") final Object thisObj, Object o, long offset) { - @JavacBug(id = 6995200) - Double result = UnsafeLoadNode.load(o, 0, offset, Kind.Double); - return result; - } - - @MethodSubstitution(isStatic = false) - public static double getDoubleVolatile(final Object thisObj, Object o, long offset) { - MembarNode.memoryBarrier(MemoryBarriers.JMM_PRE_VOLATILE_READ); - double result = getDouble(thisObj, o, offset); - MembarNode.memoryBarrier(MemoryBarriers.JMM_POST_VOLATILE_READ); - return result; - } - - @MethodSubstitution(isStatic = false) - public static void putDouble(@SuppressWarnings("unused") final Object thisObj, Object o, long offset, double x) { - UnsafeStoreNode.store(o, 0, offset, x, Kind.Double); - } - - @MethodSubstitution(isStatic = false) - public static void putDoubleVolatile(final Object thisObj, Object o, long offset, double x) { - MembarNode.memoryBarrier(MemoryBarriers.JMM_PRE_VOLATILE_WRITE); - putDouble(thisObj, o, offset, x); - MembarNode.memoryBarrier(MemoryBarriers.JMM_POST_VOLATILE_WRITE); - } - - @MethodSubstitution(isStatic = false) - public static void putByte(@SuppressWarnings("unused") final Object thisObj, long address, byte value) { - DirectStoreNode.store(address, value); - } - - @MethodSubstitution(isStatic = false) - public static void putShort(@SuppressWarnings("unused") final Object thisObj, long address, short value) { - DirectStoreNode.store(address, value); - } - - @MethodSubstitution(isStatic = false) - public static void putChar(@SuppressWarnings("unused") final Object thisObj, long address, char value) { - DirectStoreNode.store(address, value); - } - - @MethodSubstitution(isStatic = false) - public static void putInt(@SuppressWarnings("unused") final Object thisObj, long address, int value) { - DirectStoreNode.store(address, value); - } - - @MethodSubstitution(isStatic = false) - public static void putLong(@SuppressWarnings("unused") final Object thisObj, long address, long value) { - DirectStoreNode.store(address, value); - } - - @MethodSubstitution(isStatic = false) - public static void putFloat(@SuppressWarnings("unused") final Object thisObj, long address, float value) { - DirectStoreNode.store(address, value); - } - - @MethodSubstitution(isStatic = false) - public static void putDouble(@SuppressWarnings("unused") final Object thisObj, long address, double value) { - DirectStoreNode.store(address, value); - } - - @MethodSubstitution(isStatic = false) - public static byte getByte(@SuppressWarnings("unused") final Object thisObj, long address) { - return DirectReadNode.read(address, Kind.Byte); - } - - @MethodSubstitution(isStatic = false) - public static short getShort(@SuppressWarnings("unused") final Object thisObj, long address) { - return DirectReadNode.read(address, Kind.Short); - } - - @MethodSubstitution(isStatic = false) - public static char getChar(@SuppressWarnings("unused") final Object thisObj, long address) { - return DirectReadNode.read(address, Kind.Char); - } - - @MethodSubstitution(isStatic = false) - public static int getInt(@SuppressWarnings("unused") final Object thisObj, long address) { - return DirectReadNode.read(address, Kind.Int); - } - - @MethodSubstitution(isStatic = false) - public static long getLong(@SuppressWarnings("unused") final Object thisObj, long address) { - return DirectReadNode.read(address, Kind.Long); - } - - @MethodSubstitution(isStatic = false) - public static float getFloat(@SuppressWarnings("unused") final Object thisObj, long address) { - return DirectReadNode.read(address, Kind.Float); - } - - @MethodSubstitution(isStatic = false) - public static double getDouble(@SuppressWarnings("unused") final Object thisObj, long address) { - return DirectReadNode.read(address, Kind.Double); - } -} diff -r 36dafe48bc38 -r 42b6e0905881 graal/com.oracle.graal.snippets/src/com/oracle/graal/snippets/UnsafeSubstitutions.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.snippets/src/com/oracle/graal/snippets/UnsafeSubstitutions.java Wed Jan 16 09:08:24 2013 +0100 @@ -0,0 +1,382 @@ +/* + * 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.code.*; +import com.oracle.graal.api.meta.*; +import com.oracle.graal.nodes.extended.*; +import com.oracle.graal.nodes.java.*; +import com.oracle.graal.snippets.ClassSubstitution.MethodSubstitution; +import com.oracle.graal.snippets.nodes.*; + +/** + * Substitutions for {@link sun.misc.Unsafe} methods. + */ +@ClassSubstitution(sun.misc.Unsafe.class) +public class UnsafeSubstitutions { + @MethodSubstitution(isStatic = false) + public static boolean compareAndSwapObject(@SuppressWarnings("unused") final Object thisObj, Object o, long offset, Object expected, Object x) { + return CompareAndSwapNode.compareAndSwap(o, 0, offset, expected, x); + } + + @MethodSubstitution(isStatic = false) + public static boolean compareAndSwapInt(@SuppressWarnings("unused") final Object thisObj, Object o, long offset, int expected, int x) { + return CompareAndSwapNode.compareAndSwap(o, 0, offset, expected, x); + } + + @MethodSubstitution(isStatic = false) + public static boolean compareAndSwapLong(@SuppressWarnings("unused") final Object thisObj, Object o, long offset, long expected, long x) { + return CompareAndSwapNode.compareAndSwap(o, 0, offset, expected, x); + } + + @MethodSubstitution(isStatic = false) + public static Object getObject(@SuppressWarnings("unused") final Object thisObj, Object o, long offset) { + return UnsafeLoadNode.load(o, 0, offset, Kind.Object); + } + + @MethodSubstitution(isStatic = false) + public static Object getObjectVolatile(final Object thisObj, Object o, long offset) { + MembarNode.memoryBarrier(MemoryBarriers.JMM_PRE_VOLATILE_READ); + Object result = getObject(thisObj, o, offset); + MembarNode.memoryBarrier(MemoryBarriers.JMM_POST_VOLATILE_READ); + return result; + } + + @MethodSubstitution(isStatic = false) + public static void putObject(@SuppressWarnings("unused") final Object thisObj, Object o, long offset, Object x) { + UnsafeStoreNode.store(o, 0, offset, x, Kind.Object); + } + + @MethodSubstitution(isStatic = false) + public static void putObjectVolatile(final Object thisObj, Object o, long offset, Object x) { + MembarNode.memoryBarrier(MemoryBarriers.JMM_PRE_VOLATILE_WRITE); + putObject(thisObj, o, offset, x); + MembarNode.memoryBarrier(MemoryBarriers.JMM_POST_VOLATILE_WRITE); + } + + @MethodSubstitution(isStatic = false) + public static void putOrderedObject(final Object thisObj, Object o, long offset, Object x) { + MembarNode.memoryBarrier(MemoryBarriers.JMM_PRE_VOLATILE_WRITE); + putObject(thisObj, o, offset, x); + MembarNode.memoryBarrier(MemoryBarriers.JMM_POST_VOLATILE_WRITE); + } + + @MethodSubstitution(isStatic = false) + public static int getInt(@SuppressWarnings("unused") final Object thisObj, Object o, long offset) { + Integer value = UnsafeLoadNode.load(o, 0, offset, Kind.Int); + return value; + } + + @MethodSubstitution(isStatic = false) + public static int getIntVolatile(final Object thisObj, Object o, long offset) { + MembarNode.memoryBarrier(MemoryBarriers.JMM_PRE_VOLATILE_READ); + int result = getInt(thisObj, o, offset); + MembarNode.memoryBarrier(MemoryBarriers.JMM_POST_VOLATILE_READ); + return result; + } + + @MethodSubstitution(isStatic = false) + public static void putInt(@SuppressWarnings("unused") final Object thisObj, Object o, long offset, int x) { + UnsafeStoreNode.store(o, 0, offset, x, Kind.Int); + } + + @MethodSubstitution(isStatic = false) + public static void putIntVolatile(final Object thisObj, Object o, long offset, int x) { + MembarNode.memoryBarrier(MemoryBarriers.JMM_PRE_VOLATILE_WRITE); + putInt(thisObj, o, offset, x); + MembarNode.memoryBarrier(MemoryBarriers.JMM_POST_VOLATILE_WRITE); + } + + @MethodSubstitution(isStatic = false) + public static void putOrderedInt(final Object thisObj, Object o, long offset, int x) { + MembarNode.memoryBarrier(MemoryBarriers.JMM_PRE_VOLATILE_WRITE); + putInt(thisObj, o, offset, x); + MembarNode.memoryBarrier(MemoryBarriers.JMM_POST_VOLATILE_WRITE); + } + + @MethodSubstitution(isStatic = false) + public static boolean getBoolean(@SuppressWarnings("unused") final Object thisObj, Object o, long offset) { + @JavacBug(id = 6995200) + Boolean result = UnsafeLoadNode.load(o, 0, offset, Kind.Boolean); + return result; + } + + @MethodSubstitution(isStatic = false) + public static boolean getBooleanVolatile(final Object thisObj, Object o, long offset) { + MembarNode.memoryBarrier(MemoryBarriers.JMM_PRE_VOLATILE_READ); + boolean result = getBoolean(thisObj, o, offset); + MembarNode.memoryBarrier(MemoryBarriers.JMM_POST_VOLATILE_READ); + return result; + } + + @MethodSubstitution(isStatic = false) + public static void putBoolean(@SuppressWarnings("unused") final Object thisObj, Object o, long offset, boolean x) { + UnsafeStoreNode.store(o, 0, offset, x, Kind.Boolean); + } + + @MethodSubstitution(isStatic = false) + public static void putBooleanVolatile(final Object thisObj, Object o, long offset, boolean x) { + MembarNode.memoryBarrier(MemoryBarriers.JMM_PRE_VOLATILE_WRITE); + putBoolean(thisObj, o, offset, x); + MembarNode.memoryBarrier(MemoryBarriers.JMM_POST_VOLATILE_WRITE); + } + + @MethodSubstitution(isStatic = false) + public static byte getByte(@SuppressWarnings("unused") final Object thisObj, Object o, long offset) { + @JavacBug(id = 6995200) + Byte result = UnsafeLoadNode.load(o, 0, offset, Kind.Byte); + return result; + } + + @MethodSubstitution(isStatic = false) + public static byte getByteVolatile(final Object thisObj, Object o, long offset) { + MembarNode.memoryBarrier(MemoryBarriers.JMM_PRE_VOLATILE_READ); + byte result = getByte(thisObj, o, offset); + MembarNode.memoryBarrier(MemoryBarriers.JMM_POST_VOLATILE_READ); + return result; + } + + @MethodSubstitution(isStatic = false) + public static void putByte(@SuppressWarnings("unused") final Object thisObj, Object o, long offset, byte x) { + UnsafeStoreNode.store(o, 0, offset, x, Kind.Byte); + } + + @MethodSubstitution(isStatic = false) + public static void putByteVolatile(final Object thisObj, Object o, long offset, byte x) { + MembarNode.memoryBarrier(MemoryBarriers.JMM_PRE_VOLATILE_WRITE); + putByte(thisObj, o, offset, x); + MembarNode.memoryBarrier(MemoryBarriers.JMM_POST_VOLATILE_WRITE); + } + + @MethodSubstitution(isStatic = false) + public static short getShort(@SuppressWarnings("unused") final Object thisObj, Object o, long offset) { + @JavacBug(id = 6995200) + Short result = UnsafeLoadNode.load(o, 0, offset, Kind.Short); + return result; + } + + @MethodSubstitution(isStatic = false) + public static short getShortVolatile(final Object thisObj, Object o, long offset) { + MembarNode.memoryBarrier(MemoryBarriers.JMM_PRE_VOLATILE_READ); + short result = getShort(thisObj, o, offset); + MembarNode.memoryBarrier(MemoryBarriers.JMM_POST_VOLATILE_READ); + return result; + } + + @MethodSubstitution(isStatic = false) + public static void putShort(@SuppressWarnings("unused") final Object thisObj, Object o, long offset, short x) { + UnsafeStoreNode.store(o, 0, offset, x, Kind.Short); + } + + @MethodSubstitution(isStatic = false) + public static void putShortVolatile(final Object thisObj, Object o, long offset, short x) { + MembarNode.memoryBarrier(MemoryBarriers.JMM_PRE_VOLATILE_WRITE); + putShort(thisObj, o, offset, x); + MembarNode.memoryBarrier(MemoryBarriers.JMM_POST_VOLATILE_WRITE); + } + + @MethodSubstitution(isStatic = false) + public static char getChar(@SuppressWarnings("unused") final Object thisObj, Object o, long offset) { + @JavacBug(id = 6995200) + Character result = UnsafeLoadNode.load(o, 0, offset, Kind.Char); + return result; + } + + @MethodSubstitution(isStatic = false) + public static char getCharVolatile(final Object thisObj, Object o, long offset) { + MembarNode.memoryBarrier(MemoryBarriers.JMM_PRE_VOLATILE_READ); + char result = getChar(thisObj, o, offset); + MembarNode.memoryBarrier(MemoryBarriers.JMM_POST_VOLATILE_READ); + return result; + } + + @MethodSubstitution(isStatic = false) + public static void putChar(@SuppressWarnings("unused") final Object thisObj, Object o, long offset, char x) { + UnsafeStoreNode.store(o, 0, offset, x, Kind.Char); + } + + @MethodSubstitution(isStatic = false) + public static void putCharVolatile(final Object thisObj, Object o, long offset, char x) { + MembarNode.memoryBarrier(MemoryBarriers.JMM_PRE_VOLATILE_WRITE); + putChar(thisObj, o, offset, x); + MembarNode.memoryBarrier(MemoryBarriers.JMM_POST_VOLATILE_WRITE); + } + + @MethodSubstitution(isStatic = false) + public static long getLong(@SuppressWarnings("unused") final Object thisObj, Object o, long offset) { + @JavacBug(id = 6995200) + Long result = UnsafeLoadNode.load(o, 0, offset, Kind.Long); + return result; + } + + @MethodSubstitution(isStatic = false) + public static long getLongVolatile(final Object thisObj, Object o, long offset) { + MembarNode.memoryBarrier(MemoryBarriers.JMM_PRE_VOLATILE_READ); + long result = getLong(thisObj, o, offset); + MembarNode.memoryBarrier(MemoryBarriers.JMM_POST_VOLATILE_READ); + return result; + } + + @MethodSubstitution(isStatic = false) + public static void putLong(@SuppressWarnings("unused") final Object thisObj, Object o, long offset, long x) { + UnsafeStoreNode.store(o, 0, offset, x, Kind.Long); + } + + @MethodSubstitution(isStatic = false) + public static void putLongVolatile(final Object thisObj, Object o, long offset, long x) { + MembarNode.memoryBarrier(MemoryBarriers.JMM_PRE_VOLATILE_WRITE); + putLong(thisObj, o, offset, x); + MembarNode.memoryBarrier(MemoryBarriers.JMM_POST_VOLATILE_WRITE); + } + + @MethodSubstitution(isStatic = false) + public static void putOrderedLong(final Object thisObj, Object o, long offset, long x) { + MembarNode.memoryBarrier(MemoryBarriers.JMM_PRE_VOLATILE_WRITE); + putLong(thisObj, o, offset, x); + MembarNode.memoryBarrier(MemoryBarriers.JMM_POST_VOLATILE_WRITE); + } + + @MethodSubstitution(isStatic = false) + public static float getFloat(@SuppressWarnings("unused") final Object thisObj, Object o, long offset) { + @JavacBug(id = 6995200) + Float result = UnsafeLoadNode.load(o, 0, offset, Kind.Float); + return result; + } + + @MethodSubstitution(isStatic = false) + public static float getFloatVolatile(final Object thisObj, Object o, long offset) { + MembarNode.memoryBarrier(MemoryBarriers.JMM_PRE_VOLATILE_READ); + float result = getFloat(thisObj, o, offset); + MembarNode.memoryBarrier(MemoryBarriers.JMM_POST_VOLATILE_READ); + return result; + } + + @MethodSubstitution(isStatic = false) + public static void putFloat(@SuppressWarnings("unused") final Object thisObj, Object o, long offset, float x) { + UnsafeStoreNode.store(o, 0, offset, x, Kind.Float); + } + + @MethodSubstitution(isStatic = false) + public static void putFloatVolatile(final Object thisObj, Object o, long offset, float x) { + MembarNode.memoryBarrier(MemoryBarriers.JMM_PRE_VOLATILE_WRITE); + putFloat(thisObj, o, offset, x); + MembarNode.memoryBarrier(MemoryBarriers.JMM_POST_VOLATILE_WRITE); + } + + @MethodSubstitution(isStatic = false) + public static double getDouble(@SuppressWarnings("unused") final Object thisObj, Object o, long offset) { + @JavacBug(id = 6995200) + Double result = UnsafeLoadNode.load(o, 0, offset, Kind.Double); + return result; + } + + @MethodSubstitution(isStatic = false) + public static double getDoubleVolatile(final Object thisObj, Object o, long offset) { + MembarNode.memoryBarrier(MemoryBarriers.JMM_PRE_VOLATILE_READ); + double result = getDouble(thisObj, o, offset); + MembarNode.memoryBarrier(MemoryBarriers.JMM_POST_VOLATILE_READ); + return result; + } + + @MethodSubstitution(isStatic = false) + public static void putDouble(@SuppressWarnings("unused") final Object thisObj, Object o, long offset, double x) { + UnsafeStoreNode.store(o, 0, offset, x, Kind.Double); + } + + @MethodSubstitution(isStatic = false) + public static void putDoubleVolatile(final Object thisObj, Object o, long offset, double x) { + MembarNode.memoryBarrier(MemoryBarriers.JMM_PRE_VOLATILE_WRITE); + putDouble(thisObj, o, offset, x); + MembarNode.memoryBarrier(MemoryBarriers.JMM_POST_VOLATILE_WRITE); + } + + @MethodSubstitution(isStatic = false) + public static void putByte(@SuppressWarnings("unused") final Object thisObj, long address, byte value) { + DirectStoreNode.store(address, value); + } + + @MethodSubstitution(isStatic = false) + public static void putShort(@SuppressWarnings("unused") final Object thisObj, long address, short value) { + DirectStoreNode.store(address, value); + } + + @MethodSubstitution(isStatic = false) + public static void putChar(@SuppressWarnings("unused") final Object thisObj, long address, char value) { + DirectStoreNode.store(address, value); + } + + @MethodSubstitution(isStatic = false) + public static void putInt(@SuppressWarnings("unused") final Object thisObj, long address, int value) { + DirectStoreNode.store(address, value); + } + + @MethodSubstitution(isStatic = false) + public static void putLong(@SuppressWarnings("unused") final Object thisObj, long address, long value) { + DirectStoreNode.store(address, value); + } + + @MethodSubstitution(isStatic = false) + public static void putFloat(@SuppressWarnings("unused") final Object thisObj, long address, float value) { + DirectStoreNode.store(address, value); + } + + @MethodSubstitution(isStatic = false) + public static void putDouble(@SuppressWarnings("unused") final Object thisObj, long address, double value) { + DirectStoreNode.store(address, value); + } + + @MethodSubstitution(isStatic = false) + public static byte getByte(@SuppressWarnings("unused") final Object thisObj, long address) { + return DirectReadNode.read(address, Kind.Byte); + } + + @MethodSubstitution(isStatic = false) + public static short getShort(@SuppressWarnings("unused") final Object thisObj, long address) { + return DirectReadNode.read(address, Kind.Short); + } + + @MethodSubstitution(isStatic = false) + public static char getChar(@SuppressWarnings("unused") final Object thisObj, long address) { + return DirectReadNode.read(address, Kind.Char); + } + + @MethodSubstitution(isStatic = false) + public static int getInt(@SuppressWarnings("unused") final Object thisObj, long address) { + return DirectReadNode.read(address, Kind.Int); + } + + @MethodSubstitution(isStatic = false) + public static long getLong(@SuppressWarnings("unused") final Object thisObj, long address) { + return DirectReadNode.read(address, Kind.Long); + } + + @MethodSubstitution(isStatic = false) + public static float getFloat(@SuppressWarnings("unused") final Object thisObj, long address) { + return DirectReadNode.read(address, Kind.Float); + } + + @MethodSubstitution(isStatic = false) + public static double getDouble(@SuppressWarnings("unused") final Object thisObj, long address) { + return DirectReadNode.read(address, Kind.Double); + } +} diff -r 36dafe48bc38 -r 42b6e0905881 graal/com.oracle.graal.snippets/src/com/oracle/graal/snippets/UnsignedMathSnippets.java --- a/graal/com.oracle.graal.snippets/src/com/oracle/graal/snippets/UnsignedMathSnippets.java Wed Jan 16 09:05:48 2013 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,127 +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.snippets; - -import static com.oracle.graal.nodes.MaterializeNode.*; -import static com.oracle.graal.nodes.calc.Condition.*; - -import com.oracle.graal.api.code.*; -import com.oracle.graal.api.meta.*; -import com.oracle.graal.nodes.calc.*; - -/** - * 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); - } - - /** - * Unsigned division for two numbers. - */ - public static int divide(int a, int b) { - return unsignedDivide(Kind.Int, a, b); - } - - /** - * Unsigned remainder for two numbers. - */ - public static int remainder(int a, int b) { - return unsignedRemainder(Kind.Int, a, b); - } - - /** - * Unsigned division for two numbers. - */ - public static long divide(long a, long b) { - return unsignedDivide(Kind.Long, a, b); - } - - /** - * Unsigned remainder for two numbers. - */ - public static long remainder(long a, long b) { - return unsignedRemainder(Kind.Long, a, b); - } - - @NodeIntrinsic(UnsignedDivNode.class) - private static native int unsignedDivide(@ConstantNodeParameter Kind kind, int a, int b); - - @NodeIntrinsic(UnsignedDivNode.class) - private static native long unsignedDivide(@ConstantNodeParameter Kind kind, long a, long b); - - @NodeIntrinsic(UnsignedRemNode.class) - private static native int unsignedRemainder(@ConstantNodeParameter Kind kind, int a, int b); - - @NodeIntrinsic(UnsignedRemNode.class) - private static native long unsignedRemainder(@ConstantNodeParameter Kind kind, long a, long b); -} diff -r 36dafe48bc38 -r 42b6e0905881 graal/com.oracle.graal.snippets/src/com/oracle/graal/snippets/UnsignedMathSubstitutions.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.snippets/src/com/oracle/graal/snippets/UnsignedMathSubstitutions.java Wed Jan 16 09:08:24 2013 +0100 @@ -0,0 +1,140 @@ +/* + * 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 static com.oracle.graal.nodes.MaterializeNode.*; +import static com.oracle.graal.nodes.calc.Condition.*; + +import com.oracle.graal.api.code.*; +import com.oracle.graal.api.meta.*; +import com.oracle.graal.nodes.calc.*; +import com.oracle.graal.snippets.ClassSubstitution.*; + +/** + * Substitutions for {@link UnsignedMath}. + */ +@ClassSubstitution(UnsignedMath.class) +public class UnsignedMathSubstitutions { + + @MethodSubstitution + public static boolean aboveThan(int a, int b) { + return materialize(BT, b, a); + } + + @MethodSubstitution + public static boolean aboveOrEqual(int a, int b) { + return !materialize(BT, a, b); + } + + /** + * Unsigned comparison belowThan for two numbers. + */ + @MethodSubstitution + public static boolean belowThan(int a, int b) { + return materialize(BT, a, b); + } + + /** + * Unsigned comparison belowOrEqual for two numbers. + */ + @MethodSubstitution + public static boolean belowOrEqual(int a, int b) { + return !materialize(BT, b, a); + } + + /** + * Unsigned comparison aboveThan for two numbers. + */ + @MethodSubstitution + public static boolean aboveThan(long a, long b) { + return materialize(BT, b, a); + } + + /** + * Unsigned comparison aboveOrEqual for two numbers. + */ + @MethodSubstitution + public static boolean aboveOrEqual(long a, long b) { + return !materialize(BT, a, b); + } + + /** + * Unsigned comparison belowThan for two numbers. + */ + @MethodSubstitution + public static boolean belowThan(long a, long b) { + return materialize(BT, a, b); + } + + /** + * Unsigned comparison belowOrEqual for two numbers. + */ + @MethodSubstitution + public static boolean belowOrEqual(long a, long b) { + return !materialize(BT, b, a); + } + + /** + * Unsigned division for two numbers. + */ + @MethodSubstitution + public static int divide(int a, int b) { + return unsignedDivide(Kind.Int, a, b); + } + + /** + * Unsigned remainder for two numbers. + */ + @MethodSubstitution + public static int remainder(int a, int b) { + return unsignedRemainder(Kind.Int, a, b); + } + + /** + * Unsigned division for two numbers. + */ + @MethodSubstitution + public static long divide(long a, long b) { + return unsignedDivide(Kind.Long, a, b); + } + + /** + * Unsigned remainder for two numbers. + */ + @MethodSubstitution + public static long remainder(long a, long b) { + return unsignedRemainder(Kind.Long, a, b); + } + + @NodeIntrinsic(UnsignedDivNode.class) + private static native int unsignedDivide(@ConstantNodeParameter Kind kind, int a, int b); + + @NodeIntrinsic(UnsignedDivNode.class) + private static native long unsignedDivide(@ConstantNodeParameter Kind kind, long a, long b); + + @NodeIntrinsic(UnsignedRemNode.class) + private static native int unsignedRemainder(@ConstantNodeParameter Kind kind, int a, int b); + + @NodeIntrinsic(UnsignedRemNode.class) + private static native long unsignedRemainder(@ConstantNodeParameter Kind kind, long a, long b); +} diff -r 36dafe48bc38 -r 42b6e0905881 graal/com.oracle.graal.snippets/src/com/oracle/graal/snippets/nodes/BranchProbabilityNode.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.snippets/src/com/oracle/graal/snippets/nodes/BranchProbabilityNode.java Wed Jan 16 09:08:24 2013 +0100 @@ -0,0 +1,69 @@ +/* + * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.graal.snippets.nodes; + +import com.oracle.graal.nodes.*; +import com.oracle.graal.nodes.spi.*; +import com.oracle.graal.nodes.type.*; +import com.oracle.graal.nodes.util.*; + +/** + * Instances of this node class will look for a preceding if node and put the given probability into the if node's taken + * probability. Then the branch probability node will be removed. This node is intended primarily for snippets, so that + * they can define their fast and slow paths. + */ +public class BranchProbabilityNode extends FixedWithNextNode implements Simplifiable { + + private final double probability; + + public BranchProbabilityNode(double probability) { + super(StampFactory.forVoid()); + assert probability >= 0 && probability <= 1; + this.probability = probability; + } + + @Override + public void simplify(SimplifierTool tool) { + FixedNode current = this; + while (!(current instanceof BeginNode)) { + current = (FixedNode) current.predecessor(); + } + BeginNode begin = (BeginNode) current; + assert begin.predecessor() instanceof IfNode : "explicit branch probability cannot follow a merge, only if nodes"; + IfNode ifNode = (IfNode) begin.predecessor(); + if (ifNode.trueSuccessor() == begin) { + ifNode.setTakenProbability(probability); + } else { + ifNode.setTakenProbability(1 - probability); + } + + FixedNode next = next(); + setNext(null); + ((FixedWithNextNode) predecessor()).setNext(next); + GraphUtil.killCFG(this); + } + + @NodeIntrinsic + public static native void probability(@ConstantNodeParameter double probability); + +} diff -r 36dafe48bc38 -r 42b6e0905881 graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/PartialEscapeAnalysisPhase.java --- a/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/PartialEscapeAnalysisPhase.java Wed Jan 16 09:05:48 2013 +0100 +++ b/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/PartialEscapeAnalysisPhase.java Wed Jan 16 09:08:24 2013 +0100 @@ -33,6 +33,7 @@ import com.oracle.graal.nodes.spi.*; import com.oracle.graal.phases.*; import com.oracle.graal.phases.common.*; +import com.oracle.graal.phases.common.CanonicalizerPhase.*; import com.oracle.graal.phases.graph.*; import com.oracle.graal.phases.schedule.*; import com.oracle.graal.virtual.phases.ea.EffectList.Effect; @@ -42,6 +43,7 @@ private final TargetDescription target; private final MetaAccessProvider runtime; private final Assumptions assumptions; + private CustomCanonicalizer customCanonicalizer; private final boolean iterative; public PartialEscapeAnalysisPhase(TargetDescription target, MetaAccessProvider runtime, Assumptions assumptions, boolean iterative) { @@ -51,6 +53,10 @@ this.iterative = iterative; } + public void setCustomCanonicalizer(CustomCanonicalizer customCanonicalizer) { + this.customCanonicalizer = customCanonicalizer; + } + public static final void trace(String format, Object... obj) { if (GraalOptions.TraceEscapeAnalysis) { Debug.log(format, obj); @@ -108,7 +114,7 @@ return false; } if (GraalOptions.OptCanonicalizer) { - new CanonicalizerPhase(target, runtime, assumptions).apply(graph); + new CanonicalizerPhase(target, runtime, assumptions, null, customCanonicalizer).apply(graph); } return true; } diff -r 36dafe48bc38 -r 42b6e0905881 graal/com.oracle.graal.word/src/com/oracle/graal/word/Word.java --- a/graal/com.oracle.graal.word/src/com/oracle/graal/word/Word.java Wed Jan 16 09:05:48 2013 +0100 +++ b/graal/com.oracle.graal.word/src/com/oracle/graal/word/Word.java Wed Jan 16 09:08:24 2013 +0100 @@ -202,11 +202,11 @@ return signedDivide((Word) val); } @Override - @Operation(node = IntegerMulNode.class) + @Operation(node = IntegerDivNode.class) public Word signedDivide(int val) { return signedDivide(intParam(val)); } - @Operation(node = IntegerMulNode.class) + @Operation(node = IntegerDivNode.class) public Word signedDivide(Word val) { return box(unbox() / val.unbox()); } diff -r 36dafe48bc38 -r 42b6e0905881 graal/com.oracle.graal.word/src/com/oracle/graal/word/phases/WordTypeRewriterPhase.java --- a/graal/com.oracle.graal.word/src/com/oracle/graal/word/phases/WordTypeRewriterPhase.java Wed Jan 16 09:05:48 2013 +0100 +++ b/graal/com.oracle.graal.word/src/com/oracle/graal/word/phases/WordTypeRewriterPhase.java Wed Jan 16 09:08:24 2013 +0100 @@ -121,7 +121,7 @@ assert arguments.size() == 2; ValueNode left = arguments.get(0); ValueNode right = operation.rightOperandIsInt() ? toUnsigned(graph, arguments.get(1), Kind.Int) : fromSigned(graph, arguments.get(1)); - replace(invoke, nodeClassOp(graph, operation.node(), left, right)); + replace(invoke, nodeClassOp(graph, operation.node(), left, right, invoke)); break; case COMPARISON: @@ -215,10 +215,14 @@ } } - private ValueNode nodeClassOp(StructuredGraph graph, Class nodeClass, ValueNode left, ValueNode right) { + private ValueNode nodeClassOp(StructuredGraph graph, Class nodeClass, ValueNode left, ValueNode right, Invoke invoke) { try { Constructor< ? extends ValueNode> constructor = nodeClass.getConstructor(Kind.class, ValueNode.class, ValueNode.class); - return graph.add(constructor.newInstance(wordKind, left, right)); + ValueNode result = graph.add(constructor.newInstance(wordKind, left, right)); + if (result instanceof FixedWithNextNode) { + graph.addBeforeFixed(invoke.node(), (FixedWithNextNode) result); + } + return result; } catch (Throwable ex) { throw new GraalInternalError(ex).addContext(nodeClass.getName()); } diff -r 36dafe48bc38 -r 42b6e0905881 graal/com.oracle.truffle.api/src/com/oracle/truffle/api/impl/DefaultCallTarget.java --- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/impl/DefaultCallTarget.java Wed Jan 16 09:05:48 2013 +0100 +++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/impl/DefaultCallTarget.java Wed Jan 16 09:08:24 2013 +0100 @@ -26,12 +26,12 @@ import com.oracle.truffle.api.frame.*; import com.oracle.truffle.api.nodes.*; -final class DefaultCallTarget extends CallTarget { +public class DefaultCallTarget extends CallTarget { protected final RootNode rootNode; protected final FrameDescriptor frameDescriptor; - DefaultCallTarget(RootNode function, FrameDescriptor frameDescriptor) { + protected DefaultCallTarget(RootNode function, FrameDescriptor frameDescriptor) { this.rootNode = function; this.frameDescriptor = frameDescriptor; } diff -r 36dafe48bc38 -r 42b6e0905881 graal/com.oracle.truffle.api/src/com/oracle/truffle/api/impl/DefaultVirtualFrame.java --- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/impl/DefaultVirtualFrame.java Wed Jan 16 09:05:48 2013 +0100 +++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/impl/DefaultVirtualFrame.java Wed Jan 16 09:08:24 2013 +0100 @@ -27,7 +27,7 @@ import com.oracle.truffle.api.*; import com.oracle.truffle.api.frame.*; -final class DefaultVirtualFrame implements VirtualFrame { +public final class DefaultVirtualFrame implements VirtualFrame { private static final Object UNDEFINED_OBJECT = null; private static final Boolean UNDEFINED_BOOLEAN = false; @@ -43,7 +43,7 @@ protected Object[] locals; protected Class[] tags; - DefaultVirtualFrame(FrameDescriptor descriptor, PackedFrame caller, Arguments arguments) { + public DefaultVirtualFrame(FrameDescriptor descriptor, PackedFrame caller, Arguments arguments) { this.descriptor = descriptor; this.caller = caller; this.arguments = arguments; diff -r 36dafe48bc38 -r 42b6e0905881 graal/com.oracle.truffle.codegen.processor/src/META-INF/services/javax.annotation.processing.Processor --- a/graal/com.oracle.truffle.codegen.processor/src/META-INF/services/javax.annotation.processing.Processor Wed Jan 16 09:05:48 2013 +0100 +++ b/graal/com.oracle.truffle.codegen.processor/src/META-INF/services/javax.annotation.processing.Processor Wed Jan 16 09:08:24 2013 +0100 @@ -1,1 +1,1 @@ -com.oracle.truffle.codegen.processor.TruffleProcessor \ No newline at end of file +com.oracle.truffle.codegen.processor.TruffleProcessor diff -r 36dafe48bc38 -r 42b6e0905881 graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/parser/Parser.frame --- a/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/parser/Parser.frame Wed Jan 16 09:05:48 2013 +0100 +++ b/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/parser/Parser.frame Wed Jan 16 09:08:24 2013 +0100 @@ -46,7 +46,7 @@ public final Scanner scanner; public final Errors errors; private final NodeFactory factory; - -->declarations + -->declarations public Parser(Scanner scanner, NodeFactory factory) { this.scanner = scanner; this.factory = factory; diff -r 36dafe48bc38 -r 42b6e0905881 graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/parser/Scanner.frame --- a/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/parser/Scanner.frame Wed Jan 16 09:05:48 2013 +0100 +++ b/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/parser/Scanner.frame Wed Jan 16 09:08:24 2013 +0100 @@ -403,7 +403,7 @@ NextCh(); } } - + -->comments void CheckLiteral() { @@ -418,7 +418,7 @@ Token NextToken() { while (ch == ' ' || -->scan1 - ) NextCh(); + ) NextCh(); -->scan2 int recKind = noSym; int recEnd = pos; diff -r 36dafe48bc38 -r 42b6e0905881 graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/parser/SimpleLanguage.atg --- a/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/parser/SimpleLanguage.atg Wed Jan 16 09:05:48 2013 +0100 +++ b/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/parser/SimpleLanguage.atg Wed Jan 16 09:08:24 2013 +0100 @@ -28,7 +28,7 @@ = Function { - Function + Function } . @@ -86,7 +86,7 @@ } ";" (. result = factory.createPrint(expressions); .) . - + ReturnStatement = "return" @@ -97,8 +97,8 @@ = ValueExpression [ - ("<" | ">" | "<=" | ">=" | "==" | "!=" ) (. String op = t.val; .) - ValueExpression (. result = factory.createBinary(op, result, right); .) + ("<" | ">" | "<=" | ">=" | "==" | "!=" ) (. String op = t.val; .) + ValueExpression (. result = factory.createBinary(op, result, right); .) ] . diff -r 36dafe48bc38 -r 42b6e0905881 mx/commands.py --- a/mx/commands.py Wed Jan 16 09:05:48 2013 +0100 +++ b/mx/commands.py Wed Jan 16 09:08:24 2013 +0100 @@ -944,11 +944,11 @@ benchmarks += sanitycheck.getBootstraps() #SPECjvm2008 if ('specjvm2008' in args or 'all' in args): - benchmarks += [sanitycheck.getSPECjvm2008([], True, 120, 120)] + benchmarks += [sanitycheck.getSPECjvm2008([], False, True, 120, 120)] else: specjvms = [a[12:] for a in args if a.startswith('specjvm2008:')] for specjvm in specjvms: - benchmarks += [sanitycheck.getSPECjvm2008([specjvm], True, 120, 120)] + benchmarks += [sanitycheck.getSPECjvm2008([specjvm], False, True, 120, 120)] if ('specjbb2005' in args or 'all' in args): benchmarks += [sanitycheck.getSPECjbb2005()] @@ -966,16 +966,20 @@ def specjvm2008(args): """run one or all SPECjvm2008 benchmarks - All options begining with - will be passed to the vm except for -ikv -wt and -it. + All options begining with - will be passed to the vm except for -ikv -ict -wt and -it. Other options are supposed to be benchmark names and will be passed to SPECjvm2008.""" benchArgs = [a for a in args if a[0] != '-'] vmArgs = [a for a in args if a[0] == '-'] wt = None it = None skipValid = False + skipCheck = False if '-v' in vmArgs: vmArgs.remove('-v') benchArgs.append('-v') + if '-ict' in vmArgs: + skipCheck = True + vmArgs.remove('-ict') if '-ikv' in vmArgs: skipValid = True vmArgs.remove('-ikv') @@ -996,7 +1000,7 @@ vmArgs.remove('-it') benchArgs.remove(args[itIdx+1]) vm = _vm; - sanitycheck.getSPECjvm2008(benchArgs, skipValid, wt, it).bench(vm, opts=vmArgs) + sanitycheck.getSPECjvm2008(benchArgs, skipCheck, skipValid, wt, it).bench(vm, opts=vmArgs) def hsdis(args, copyToDir=None): """download the hsdis library diff -r 36dafe48bc38 -r 42b6e0905881 mx/projects --- a/mx/projects Wed Jan 16 09:05:48 2013 +0100 +++ b/mx/projects Wed Jan 16 09:08:24 2013 +0100 @@ -237,7 +237,7 @@ # graal.compiler.test project@com.oracle.graal.compiler.test@subDir=graal project@com.oracle.graal.compiler.test@sourceDirs=src -project@com.oracle.graal.compiler.test@dependencies=JUNIT,com.oracle.graal.compiler,com.oracle.graal.java,com.oracle.graal.api.runtime +project@com.oracle.graal.compiler.test@dependencies=com.oracle.graal.api.runtime,com.oracle.graal.printer,JUNIT project@com.oracle.graal.compiler.test@checkstyle=com.oracle.graal.graph project@com.oracle.graal.compiler.test@javaCompliance=1.7 diff -r 36dafe48bc38 -r 42b6e0905881 mx/sanitycheck.py --- a/mx/sanitycheck.py Wed Jan 16 09:05:48 2013 +0100 +++ b/mx/sanitycheck.py Wed Jan 16 09:08:24 2013 +0100 @@ -108,9 +108,9 @@ success = re.compile(r"^Valid run, Score is [0-9]+$") matcher = Matcher(score, {'const:group' : "const:SPECjbb2005", 'const:name' : 'const:score', 'const:score' : 'score'}) classpath = ['jbb.jar', 'check.jar'] - return Test("SPECjbb2005", ['spec.jbb.JBBmain', '-propfile', 'SPECjbb.props'] + benchArgs, [success], [error], [matcher], vmOpts=['-Xms3g', '-XX:+UseSerialGC', '-cp', os.pathsep.join(classpath)], defaultCwd=specjbb2005) + return Test("SPECjbb2005", ['spec.jbb.JBBmain', '-propfile', 'SPECjbb.props'] + benchArgs, [success], [error], [matcher], vmOpts=['-Xms3g', '-XX:+UseSerialGC', '-XX:-UseCompressedOops', '-cp', os.pathsep.join(classpath)], defaultCwd=specjbb2005) -def getSPECjvm2008(benchArgs = [], skipKitValidation=False, warmupTime=None, iterationTime=None): +def getSPECjvm2008(benchArgs = [], skipCheck=False, skipKitValidation=False, warmupTime=None, iterationTime=None): specjvm2008 = mx.get_env('SPECJVM2008') if specjvm2008 is None or not exists(join(specjvm2008, 'SPECjvm2008.jar')): @@ -129,8 +129,10 @@ opts += ['-it', str(iterationTime)] if skipKitValidation: opts += ['-ikv'] + if skipCheck: + opts += ['-ict'] - return Test("SPECjvm2008", ['-jar', 'SPECjvm2008.jar'] + opts + benchArgs, [success], [error], [matcher], vmOpts=['-Xms3g', '-XX:+UseSerialGC'], defaultCwd=specjvm2008) + return Test("SPECjvm2008", ['-jar', 'SPECjvm2008.jar'] + opts + benchArgs, [success], [error], [matcher], vmOpts=['-Xms3g', '-XX:+UseSerialGC', '-XX:-UseCompressedOops'], defaultCwd=specjvm2008) def getDacapos(level=SanityCheckLevel.Normal, gateBuildLevel=None, dacapoArgs=[]): checks = [] @@ -162,7 +164,7 @@ dacapoMatcher = Matcher(dacapoTime, {'const:group' : "const:DaCapo", 'const:name' : 'benchmark', 'const:score' : 'time'}, startNewLine=True) dacapoMatcher1 = Matcher(dacapoTime1, {'const:group' : "const:DaCapo-1stRun", 'const:name' : 'benchmark', 'const:score' : 'time'}) - return Test("DaCapo-" + name, ['-jar', dacapo, name, '-n', str(n), ] + dacapoArgs, [dacapoSuccess], [dacapoFail], [dacapoMatcher, dacapoMatcher1], ['-Xms2g', '-XX:+UseSerialGC']) + return Test("DaCapo-" + name, ['-jar', dacapo, name, '-n', str(n), ] + dacapoArgs, [dacapoSuccess], [dacapoFail], [dacapoMatcher, dacapoMatcher1], ['-Xms2g', '-XX:+UseSerialGC', '-XX:-UseCompressedOops']) def getScalaDacapos(level=SanityCheckLevel.Normal, gateBuildLevel=None, dacapoArgs=[]): checks = [] @@ -192,7 +194,7 @@ dacapoMatcher = Matcher(dacapoTime, {'const:group' : "const:Scala-DaCapo", 'const:name' : 'benchmark', 'const:score' : 'time'}) - return Test("Scala-DaCapo-" + name, ['-jar', dacapo, name, '-n', str(n), ] + dacapoArgs, [dacapoSuccess], [dacapoFail], [dacapoMatcher], ['-Xms2g', '-XX:+UseSerialGC']) + return Test("Scala-DaCapo-" + name, ['-jar', dacapo, name, '-n', str(n), ] + dacapoArgs, [dacapoSuccess], [dacapoFail], [dacapoMatcher], ['-Xms2g', '-XX:+UseSerialGC', '-XX:-UseCompressedOops']) def getBootstraps(): time = re.compile(r"Bootstrapping Graal\.+ in (?P