# HG changeset patch # User Roland Schatz # Date 1398676695 -7200 # Node ID 40d0022115ee38d3844856834e6e80aae115da5e # Parent 3dde8d8c95b8790746825ab51248ad6b252dbf7f# Parent d030e31fe082d109c0793553ebe4b5a2d90d9b8f Merge. diff -r 3dde8d8c95b8 -r 40d0022115ee .hgignore --- a/.hgignore Fri Apr 25 16:21:07 2014 +0200 +++ b/.hgignore Mon Apr 28 11:18:15 2014 +0200 @@ -5,6 +5,7 @@ ^mx/netbeans-config.zip ^mx/netbeans-config-libs.zip ^mx/eclipse-launches +^mx/jmh ^mx/currentAnnotationProcessors ^mx/ecj.jar ^mx/includes diff -r 3dde8d8c95b8 -r 40d0022115ee CHANGELOG.md --- a/CHANGELOG.md Fri Apr 25 16:21:07 2014 +0200 +++ b/CHANGELOG.md Mon Apr 28 11:18:15 2014 +0200 @@ -7,11 +7,18 @@ * Explicit types for inputs (InputType enum). * Added graal.version system property to Graal enabled VM builds. * Transitioned to JDK 8 as minimum JDK level for Graal. -* Added support for stack introspection +* Added support for stack introspection. +* New MatchRule facility to convert multiple HIR nodes into specialized LIR * ... ### Truffle -* Support for collecting stack traces and for accessing the current frame in slow paths +* The method CallTarget#call takes now a variable number of Object arguments. +* Support for collecting stack traces and for accessing the current frame in slow paths. +* Renamed CallNode to DirectCallNode. +* Renamed TruffleRuntime#createCallNode to TruffleRuntime#createDirectCallNode. +* Added IndirectCallNode for calls with a changing CallTarget. +* Added TruffleRuntime#createIndirectCallNode to create an IndirectCallNode. +* DirectCallNode#inline was renamed to DirectCallNode#forceInlining(). * ... ## Version 0.2 diff -r 3dde8d8c95b8 -r 40d0022115ee 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 Fri Apr 25 16:21:07 2014 +0200 +++ b/graal/com.oracle.graal.alloc/src/com/oracle/graal/alloc/ComputeBlockOrder.java Mon Apr 28 11:18:15 2014 +0200 @@ -25,6 +25,7 @@ import java.util.*; +import com.oracle.graal.compiler.common.cfg.*; import com.oracle.graal.nodes.cfg.*; /** @@ -34,12 +35,12 @@ * with the most likely path that was left out during this process. The process iteratively * continues until all blocks are scheduled. Additionally, it is guaranteed that all blocks of a * loop are scheduled before any block following the loop is scheduled. - * + * * The machine code generator order includes reordering of loop headers such that the backward jump * is a conditional jump if there is only one loop end block. Additionally, the target of loop * backward jumps are always marked as aligned. Aligning the target of conditional jumps does not * bring a measurable benefit and is therefore avoided to keep the code size small. - * + * * The linear scan register allocator order has an additional mechanism that prevents merge nodes * from being scheduled if there is at least one highly likely predecessor still unscheduled. This * increases the probability that the merge node and the corresponding predecessor are more closely @@ -63,7 +64,7 @@ /** * Computes the block order used for the linear scan register allocator. - * + * * @return sorted list of blocks */ public static > List computeLinearScanOrder(int blockCount, T startBlock, BlocksToDoubles blockProbabilities) { @@ -77,7 +78,7 @@ /** * Computes the block order used for code emission. - * + * * @return sorted list of blocks */ public static > List computeCodeEmittingOrder(int blockCount, T startBlock, BlocksToDoubles blockProbabilities) { @@ -151,7 +152,6 @@ /** * Add a linear path to the code emission order greedily following the most likely successor. */ - @SuppressWarnings("unchecked") private static > void addPathToCodeEmittingOrder(T initialBlock, List order, PriorityQueue worklist, BitSet visitedBlocks, BlocksToDoubles blockProbabilities) { T block = initialBlock; while (block != null) { @@ -166,17 +166,17 @@ addBlock(block, order); } - Loop loop = block.getLoop(); + Loop loop = block.getLoop(); if (block.isLoopEnd() && skipLoopHeader(loop.header)) { // This is the only loop end of a skipped loop header. // Add the header immediately afterwards. - addBlock((T) loop.header, order); + addBlock(loop.header, order); // Make sure the loop successors of the loop header are aligned // as they are the target // of the backward jump. - for (Block successor : loop.header.getSuccessors()) { + for (T successor : loop.header.getSuccessors()) { if (successor.getLoopDepth() == block.getLoopDepth()) { successor.setAlign(true); } @@ -230,8 +230,8 @@ * Skip the loop header block if the loop consists of more than one block and it has only a * single loop end block. */ - private static boolean skipLoopHeader(AbstractBlock block) { - return (block.isLoopHeader() && !block.isLoopEnd() && block.getLoop().loopBegin().loopEnds().count() == 1); + private static > boolean skipLoopHeader(AbstractBlock block) { + return (block.isLoopHeader() && !block.isLoopEnd() && block.getLoop().numBackedges() == 1); } /** diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/BytecodeFrame.java --- a/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/BytecodeFrame.java Fri Apr 25 16:21:07 2014 +0200 +++ b/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/BytecodeFrame.java Mon Apr 28 11:18:15 2014 +0200 @@ -94,6 +94,43 @@ public final boolean duringCall; /** + * This BCI should be used for frame states that are built for code with no meaningful BCI. + */ + public static final int UNKNOWN_BCI = -5; + + /** + * The BCI for exception unwind. This is synthetic code and has no representation in bytecode. + * In contrast with {@link #AFTER_EXCEPTION_BCI}, at this point, if the method is synchronized, + * the monitor is still held. + */ + public static final int UNWIND_BCI = -1; + + /** + * The BCI for the state before starting to execute a method. Note that if the method is + * synchronized, the monitor is not yet held. + */ + public static final int BEFORE_BCI = -2; + + /** + * The BCI for the state after finishing the execution of a method and returning normally. Note + * that if the method was synchronized the monitor is already released. + */ + public static final int AFTER_BCI = -3; + + /** + * The BCI for exception unwind. This is synthetic code and has no representation in bytecode. + * In contrast with {@link #UNWIND_BCI}, at this point, if the method is synchronized, the + * monitor is already released. + */ + public static final int AFTER_EXCEPTION_BCI = -4; + + /** + * This BCI should be used for states that cannot be the target of a deoptimization, like + * snippet frame states. + */ + public static final int INVALID_FRAMESTATE_BCI = -6; + + /** * Creates a new frame object. * * @param caller the caller frame (which may be {@code null}) diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/CodeCacheProvider.java --- a/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/CodeCacheProvider.java Fri Apr 25 16:21:07 2014 +0200 +++ b/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/CodeCacheProvider.java Mon Apr 28 11:18:15 2014 +0200 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2009, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2009, 2014, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -34,18 +34,18 @@ /** * Adds the given compilation result as an implementation of the given method without making it * the default implementation. - * + * * @param method a method to which the executable code is begin added * @param compResult the compilation result to be added * @param speculationLog the speculation log to be used - * @return a reference to the compiled and ready-to-run code or null if the code installation - * failed + * @return a reference to the compiled and ready-to-run code or throws a + * {@link BailoutException} if the code installation failed */ - InstalledCode addMethod(ResolvedJavaMethod method, CompilationResult compResult, SpeculationLog speculationLog); + InstalledCode addMethod(ResolvedJavaMethod method, CompilationResult compResult, SpeculationLog speculationLog, InstalledCode predefinedInstalledCode); /** * Sets the given compilation result as the default implementation of the given method. - * + * * @param method a method to which the executable code is begin added * @param compResult the compilation result to be added * @return a reference to the compiled and ready-to-run code or null if the code installation @@ -55,11 +55,11 @@ /** * Returns a disassembly of some compiled code. - * + * * @param compResult some compiled code * @param installedCode the result of installing the code in {@code compResult} or null if the * code has not yet been installed - * + * * @return a disassembly. This will be of length 0 if the runtime does not support * disassembling. */ @@ -73,7 +73,7 @@ /** * Minimum size of the stack area reserved for outgoing parameters. This area is reserved in all * cases, even when the compiled method has no regular call instructions. - * + * * @return the minimum size of the outgoing parameter area in bytes */ int getMinimumOutgoingSize(); @@ -93,4 +93,9 @@ * Gets a description of the target architecture. */ TargetDescription getTarget(); + + /** + * Create a new speculation log for the target runtime. + */ + SpeculationLog createSpeculationLog(); } diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/CodeUtil.java --- a/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/CodeUtil.java Fri Apr 25 16:21:07 2014 +0200 +++ b/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/CodeUtil.java Mon Apr 28 11:18:15 2014 +0200 @@ -22,7 +22,6 @@ */ package com.oracle.graal.api.code; -import java.lang.reflect.*; import java.util.*; import com.oracle.graal.api.meta.*; @@ -342,7 +341,7 @@ int sigCount = sig.getParameterCount(false); JavaType[] argTypes; int argIndex = 0; - if (!Modifier.isStatic(method.getModifiers())) { + if (!method.isStatic()) { argTypes = new JavaType[sigCount + 1]; argTypes[argIndex++] = method.getDeclaringClass(); } else { diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/CompilationResult.java --- a/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/CompilationResult.java Fri Apr 25 16:21:07 2014 +0200 +++ b/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/CompilationResult.java Mon Apr 28 11:18:15 2014 +0200 @@ -368,7 +368,7 @@ * starting address of the table. This type of table maybe generated when translating a * multi-way branch based on a key value from a dense value set (e.g. the {@code tableswitch} * JVM instruction). - * + * * The table is indexed by the contiguous range of integers from {@link #low} to {@link #high} * inclusive. */ @@ -432,22 +432,20 @@ private static final long serialVersionUID = 3612943150662354844L; public final Object id; - public final Mark[] references; - public Mark(int pcOffset, Object id, Mark[] references) { + public Mark(int pcOffset, Object id) { super(pcOffset); this.id = id; - this.references = references; } @Override public String toString() { if (id == null) { - return String.format("%d[]", pcOffset, references.length); + return String.format("%d[]", pcOffset); } else if (id instanceof Integer) { - return String.format("%d[]", pcOffset, references.length, Integer.toHexString((Integer) id)); + return String.format("%d[]", pcOffset, Integer.toHexString((Integer) id)); } else { - return String.format("%d[]", pcOffset, references.length, id.toString()); + return String.format("%d[]", pcOffset, id.toString()); } } } @@ -460,7 +458,7 @@ private final List exceptionHandlers = new ArrayList<>(); private final List marks = new ArrayList<>(); - private int frameSize = -1; + private int totalFrameSize = -1; private int customStackAreaOffset = -1; private int registerRestoreEpilogueOffset = -1; @@ -525,18 +523,29 @@ } /** - * Sets the frame size in bytes. Does not include the return address pushed onto the stack, if - * any. - * + * The total frame size of the method in bytes. This includes the return address pushed onto the + * stack, if any. + * + * @return the frame size + */ + public int getTotalFrameSize() { + assert totalFrameSize != -1 : "frame size not yet initialized!"; + return totalFrameSize; + } + + /** + * Sets the total frame size in bytes. This includes the return address pushed onto the stack, + * if any. + * * @param size the size of the frame in bytes */ - public void setFrameSize(int size) { - frameSize = size; + public void setTotalFrameSize(int size) { + totalFrameSize = size; } /** * Sets the machine that has been generated by the compiler. - * + * * @param code the machine code generated * @param size the size of the machine code */ @@ -548,7 +557,7 @@ /** * Records a reference to the data section in the code section (e.g. to load an integer or * floating point constant). - * + * * @param codePos the position in the code where the data reference occurs * @param data the data that is referenced */ @@ -559,7 +568,7 @@ /** * Records a reference to an inlined constant in the code section (e.g. to load a constant oop). - * + * * @param codePos the position in the code where the inlined constant occurs * @param data the data that is referenced */ @@ -570,7 +579,7 @@ /** * Records a call in the code array. - * + * * @param codePos the position of the call in the code array * @param size the size of the call instruction * @param target the being called @@ -584,7 +593,7 @@ /** * Records an exception handler for this method. - * + * * @param codePos the position in the code that is covered by the handler * @param handlerPos the position of the handler */ @@ -594,7 +603,7 @@ /** * Records an infopoint in the code array. - * + * * @param codePos the position of the infopoint in the code array * @param debugInfo the debug info for the infopoint */ @@ -604,10 +613,10 @@ /** * Records a custom infopoint in the code section. - * + * * Compiler implementations can use this method to record non-standard infopoints, which are not * handled by the dedicated methods like {@link #recordCall}. - * + * * @param infopoint the infopoint to record, usually a derived class from {@link Infopoint} */ public void addInfopoint(Infopoint infopoint) { @@ -621,13 +630,12 @@ /** * Records an instruction mark within this method. - * + * * @param codePos the position in the code that is covered by the handler * @param markId the identifier for this mark - * @param references an array of other marks that this mark references */ - public Mark recordMark(int codePos, Object markId, Mark[] references) { - Mark mark = new Mark(codePos, markId, references); + public Mark recordMark(int codePos, Object markId) { + Mark mark = new Mark(codePos, markId); marks.add(mark); return mark; } @@ -636,7 +644,7 @@ * Allows a method to specify the offset of the epilogue that restores the callee saved * registers. Must be called iff the method is a callee saved method and stores callee registers * on the stack. - * + * * @param registerRestoreEpilogueOffset the offset in the machine code where the epilogue begins */ public void setRegisterRestoreEpilogueOffset(int registerRestoreEpilogueOffset) { @@ -645,16 +653,6 @@ } /** - * The frame size of the method in bytes. - * - * @return the frame size - */ - public int getFrameSize() { - assert frameSize != -1 : "frame size not yet initialized!"; - return frameSize; - } - - /** * @return the code offset of the start of the epilogue that restores all callee saved * registers, or -1 if this is not a callee saved method */ @@ -664,7 +662,7 @@ /** * Offset in bytes for the custom stack area (relative to sp). - * + * * @return the offset in bytes */ public int getCustomStackAreaOffset() { diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/InstalledCode.java --- a/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/InstalledCode.java Fri Apr 25 16:21:07 2014 +0200 +++ b/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/InstalledCode.java Mon Apr 28 11:18:15 2014 +0200 @@ -22,41 +22,66 @@ */ package com.oracle.graal.api.code; -import com.oracle.graal.api.meta.*; - /** * Represents a compiled instance of a method. It may have been invalidated or removed in the * meantime. */ -public interface InstalledCode { +public class InstalledCode { + + /** + * Raw address of this code blob. + */ + private long address; + + /** + * Counts how often the address field was reassigned. + */ + private long version; /** - * Returns the method (if any) to which the installed code belongs. + * @return the address of this code blob */ - ResolvedJavaMethod getMethod(); + public final long getAddress() { + return address; + } + + /** + * @return the address of this code blob + */ + public final long getVersion() { + return version; + } /** * Returns the start address of this installed code if it is {@linkplain #isValid() valid}, 0 * otherwise. */ - long getStart(); + public long getStart() { + return 0; + } /** * Returns a copy of this installed code if it is {@linkplain #isValid() valid}, null otherwise. */ - byte[] getCode(); + public byte[] getCode() { + return null; + } /** * @return true if the code represented by this object is still valid, false otherwise (may * happen due to deopt, etc.) */ - boolean isValid(); + public boolean isValid() { + return address != 0; + } /** * Invalidates this installed code such that any subsequent invocation will throw an * {@link InvalidInstalledCodeException}. */ - void invalidate(); + public void invalidate() { + throw new UnsupportedOperationException(); + } /** * Executes the installed code with a variable number of arguments. @@ -64,5 +89,8 @@ * @param args the array of object arguments * @return the value returned by the executed code */ - Object executeVarargs(Object... args) throws InvalidInstalledCodeException; + @SuppressWarnings("unused") + public Object executeVarargs(Object... args) throws InvalidInstalledCodeException { + throw new UnsupportedOperationException(); + } } diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/TypeCheckHints.java --- a/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/TypeCheckHints.java Fri Apr 25 16:21:07 2014 +0200 +++ b/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/TypeCheckHints.java Mon Apr 28 11:18:15 2014 +0200 @@ -23,8 +23,6 @@ package com.oracle.graal.api.code; import static com.oracle.graal.api.meta.MetaUtil.*; -import static java.lang.reflect.Modifier.*; - import java.util.*; import com.oracle.graal.api.meta.*; @@ -83,7 +81,7 @@ /** * Derives hint information for use when generating the code for a type check instruction. - * + * * @param targetType the target type of the type check * @param profile the profiling information available for the instruction (if any) * @param assumptions the object in which speculations are recorded. This is null if @@ -151,10 +149,10 @@ /** * Determines if a given type can have subtypes other than itself. This analysis is purely * static; no assumptions are made. - * + * * @return true if {@code type} can have subtypes */ public static boolean canHaveSubtype(ResolvedJavaType type) { - return !isFinal(getElementalType(type).getModifiers()); + return !getElementalType(type).isFinal(); } } diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/package-info.java --- a/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/package-info.java Fri Apr 25 16:21:07 2014 +0200 +++ b/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/package-info.java Mon Apr 28 11:18:15 2014 +0200 @@ -23,7 +23,7 @@ /** * Package that defines the interface between a Java application that wants to install code and the runtime. * The runtime provides in implementation of the {@link com.oracle.graal.api.code.CodeCacheProvider} interface. - * The method {@link com.oracle.graal.api.code.CodeCacheProvider#addMethod(com.oracle.graal.api.meta.ResolvedJavaMethod, CompilationResult, SpeculationLog)} + * The method {@link com.oracle.graal.api.code.CodeCacheProvider#addMethod(com.oracle.graal.api.meta.ResolvedJavaMethod, CompilationResult, SpeculationLog, InstalledCode)} * can be used to install code for a given method. */ package com.oracle.graal.api.code; diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/stack/StackIntrospection.java --- a/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/stack/StackIntrospection.java Fri Apr 25 16:21:07 2014 +0200 +++ b/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/stack/StackIntrospection.java Mon Apr 28 11:18:15 2014 +0200 @@ -30,10 +30,10 @@ * Accesses the current stack, returning a collection of {@long InspectedFrame}s that can be * used to inspect the stack frames' contents. * - * @param initialMethod if this is non-{@code null}, then the stack trace will start at this - * method - * @param matchingMethod if this is non-{@code null}, then only matching stack frames are + * @param initialMethods if this is non-{@code null}, then the stack trace will start at these + * methods + * @param matchingMethods if this is non-{@code null}, then only matching stack frames are * returned */ - Iterable getStackTrace(ResolvedJavaMethod initialMethod, ResolvedJavaMethod matchingMethod); + Iterable getStackTrace(ResolvedJavaMethod[] initialMethods, ResolvedJavaMethod[] matchingMethods, int initialSkip); } diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.api.meta.test/src/com/oracle/graal/api/meta/test/TestResolvedJavaMethod.java --- a/graal/com.oracle.graal.api.meta.test/src/com/oracle/graal/api/meta/test/TestResolvedJavaMethod.java Fri Apr 25 16:21:07 2014 +0200 +++ b/graal/com.oracle.graal.api.meta.test/src/com/oracle/graal/api/meta/test/TestResolvedJavaMethod.java Mon Apr 28 11:18:15 2014 +0200 @@ -22,7 +22,6 @@ */ package com.oracle.graal.api.meta.test; -import static java.lang.reflect.Modifier.*; import static org.junit.Assert.*; import java.lang.annotation.*; @@ -52,9 +51,9 @@ if (code == null) { assertTrue(m.getCodeSize() == 0); } else { - if (isAbstract(m.getModifiers())) { + if (m.isAbstract()) { assertTrue(code.length == 0); - } else if (!isNative(m.getModifiers())) { + } else if (!m.isNative()) { assertTrue(code.length > 0); } } @@ -69,9 +68,9 @@ for (Map.Entry e : methods.entrySet()) { ResolvedJavaMethod m = e.getValue(); int codeSize = m.getCodeSize(); - if (isAbstract(m.getModifiers())) { + if (m.isAbstract()) { assertTrue(codeSize == 0); - } else if (!isNative(m.getModifiers())) { + } else if (!m.isNative()) { assertTrue(codeSize > 0); } } @@ -128,19 +127,33 @@ } @Test - public void canBeStaticallyBoundTest() { + public void isSynchronizedTest() { for (Map.Entry e : methods.entrySet()) { ResolvedJavaMethod m = e.getValue(); - assertEquals(m.canBeStaticallyBound(), canBeStaticallyBound(e.getKey().getModifiers())); + assertEquals(Modifier.isSynchronized(e.getKey().getModifiers()), m.isSynchronized()); } for (Map.Entry, ResolvedJavaMethod> e : constructors.entrySet()) { ResolvedJavaMethod m = e.getValue(); - assertEquals(m.canBeStaticallyBound(), canBeStaticallyBound(e.getKey().getModifiers())); + assertEquals(Modifier.isSynchronized(e.getKey().getModifiers()), m.isSynchronized()); } } - private static boolean canBeStaticallyBound(int modifiers) { - return (Modifier.isFinal(modifiers) || Modifier.isPrivate(modifiers) || Modifier.isStatic(modifiers)) && !Modifier.isAbstract(modifiers); + @Test + public void canBeStaticallyBoundTest() { + for (Map.Entry e : methods.entrySet()) { + ResolvedJavaMethod m = e.getValue(); + assertEquals(m.canBeStaticallyBound(), canBeStaticallyBound(e.getKey())); + } + for (Map.Entry, ResolvedJavaMethod> e : constructors.entrySet()) { + ResolvedJavaMethod m = e.getValue(); + assertEquals(m.canBeStaticallyBound(), canBeStaticallyBound(e.getKey())); + } + } + + private static boolean canBeStaticallyBound(Member method) { + int modifiers = method.getModifiers(); + return (Modifier.isFinal(modifiers) || Modifier.isPrivate(modifiers) || Modifier.isStatic(modifiers) || Modifier.isFinal(method.getDeclaringClass().getModifiers())) && + !Modifier.isAbstract(modifiers); } private static String methodWithExceptionHandlers(String p1, Object o2) { diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/Constant.java --- a/graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/Constant.java Fri Apr 25 16:21:07 2014 +0200 +++ b/graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/Constant.java Mon Apr 28 11:18:15 2014 +0200 @@ -138,7 +138,11 @@ public abstract double asDouble(); public String toValueString() { - return getKind().format(asBoxedPrimitive()); + if (getKind() == Kind.Illegal) { + return "illegal"; + } else { + return getKind().format(asBoxedPrimitive()); + } } @Override diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/JavaTypeProfile.java --- a/graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/JavaTypeProfile.java Fri Apr 25 16:21:07 2014 +0200 +++ b/graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/JavaTypeProfile.java Mon Apr 28 11:18:15 2014 +0200 @@ -22,8 +22,6 @@ */ package com.oracle.graal.api.meta; -import static java.lang.reflect.Modifier.*; - import java.util.*; import com.oracle.graal.api.meta.JavaTypeProfile.ProfiledType; @@ -146,7 +144,7 @@ public ProfiledType(ResolvedJavaType type, double probability) { super(type, probability); - assert type.isArray() || !isAbstract(type.getModifiers()) : type; + assert type.isArray() || !type.isAbstract() : type; } /** diff -r 3dde8d8c95b8 -r 40d0022115ee 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 Fri Apr 25 16:21:07 2014 +0200 +++ b/graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/MetaUtil.java Mon Apr 28 11:18:15 2014 +0200 @@ -22,8 +22,6 @@ */ package com.oracle.graal.api.meta; -import static java.lang.reflect.Modifier.*; - import java.io.*; import java.lang.annotation.*; import java.lang.reflect.*; @@ -378,7 +376,7 @@ break; } case 'f': { - sb.append(!(method instanceof ResolvedJavaMethod) ? "unresolved" : isStatic(((ResolvedJavaMethod) method).getModifiers()) ? "static" : "virtual"); + sb.append(!(method instanceof ResolvedJavaMethod) ? "unresolved" : ((ResolvedJavaMethod) method).isStatic() ? "static" : "virtual"); break; } case '%': { @@ -452,7 +450,7 @@ break; } case 'f': { - sb.append(!(field instanceof ResolvedJavaField) ? "unresolved" : isStatic(((ResolvedJavaField) field).getModifiers()) ? "static" : "instance"); + sb.append(!(field instanceof ResolvedJavaField) ? "unresolved" : ((ResolvedJavaField) field).isStatic() ? "static" : "instance"); break; } case '%': { @@ -561,7 +559,7 @@ } public static JavaType[] signatureToTypes(ResolvedJavaMethod method) { - JavaType receiver = isStatic(method.getModifiers()) ? null : method.getDeclaringClass(); + JavaType receiver = method.isStatic() ? null : method.getDeclaringClass(); return signatureToTypes(method.getSignature(), receiver); } diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/ModifiersProvider.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/ModifiersProvider.java Mon Apr 28 11:18:15 2014 +0200 @@ -0,0 +1,131 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.graal.api.meta; + +import static java.lang.reflect.Modifier.*; + +import java.lang.reflect.*; + +/** + * A Java element (i.e., a class, interface, field or method) that is described by a set of Java + * language {@linkplain #getModifiers() modifiers}. + */ +public interface ModifiersProvider { + + /** + * Returns the Java language modifiers for this element. + */ + int getModifiers(); + + /** + * see {@link Modifier#isInterface(int)} + */ + default boolean isInterface() { + return Modifier.isInterface(getModifiers()); + } + + /** + * see {@link Modifier#isSynchronized(int)} + */ + default boolean isSynchronized() { + return Modifier.isSynchronized(getModifiers()); + } + + /** + * see {@link Modifier#isStatic(int)} + */ + default boolean isStatic() { + return Modifier.isStatic(getModifiers()); + } + + /** + * see {@link Modifier#isFinal(int)} + */ + default boolean isFinal() { + return Modifier.isFinal(getModifiers()); + } + + /** + * see {@link Modifier#isPublic(int)} + */ + default boolean isPublic() { + return Modifier.isPublic(getModifiers()); + } + + /** + * Determines if this element is neither {@linkplain #isPublic() public}, + * {@linkplain #isProtected() protected} nor {@linkplain #isPrivate() private}. + */ + default boolean isPackagePrivate() { + return ((PUBLIC | PROTECTED | PRIVATE) & getModifiers()) == 0; + } + + /** + * see {@link Modifier#isPrivate(int)} + */ + default boolean isPrivate() { + return Modifier.isPrivate(getModifiers()); + } + + /** + * see {@link Modifier#isProtected(int)} + */ + default boolean isProtected() { + return Modifier.isProtected(getModifiers()); + } + + /** + * see {@link Modifier#isTransient(int)} + */ + default boolean isTransient() { + return Modifier.isTransient(getModifiers()); + } + + /** + * see {@link Modifier#isStrict(int)} + */ + default boolean isStrict() { + return Modifier.isStrict(getModifiers()); + } + + /** + * see {@link Modifier#isVolatile(int)} + */ + default boolean isVolatile() { + return Modifier.isVolatile(getModifiers()); + } + + /** + * see {@link Modifier#isNative(int)} + */ + default boolean isNative() { + return Modifier.isNative(getModifiers()); + } + + /** + * see {@link Modifier#isAbstract(int)} + */ + default boolean isAbstract() { + return Modifier.isAbstract(getModifiers()); + } +} diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/PrimitiveConstant.java --- a/graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/PrimitiveConstant.java Fri Apr 25 16:21:07 2014 +0200 +++ b/graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/PrimitiveConstant.java Mon Apr 28 11:18:15 2014 +0200 @@ -104,7 +104,7 @@ case Double: return Double.valueOf(asDouble()); default: - throw new IllegalArgumentException(); + throw new IllegalArgumentException("unexpected kind " + getKind()); } } diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/ResolvedJavaField.java --- a/graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/ResolvedJavaField.java Fri Apr 25 16:21:07 2014 +0200 +++ b/graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/ResolvedJavaField.java Mon Apr 28 11:18:15 2014 +0200 @@ -29,12 +29,13 @@ * Represents a reference to a resolved Java field. Fields, like methods and types, are resolved * through {@link ConstantPool constant pools}. */ -public interface ResolvedJavaField extends JavaField, LocationIdentity { +public interface ResolvedJavaField extends JavaField, LocationIdentity, ModifiersProvider { /** - * Returns the Java language modifiers for this field, as an integer. The {@link Modifier} class - * should be used to decode the modifiers. Only the {@linkplain Modifier#fieldModifiers() field - * flags} specified in the JVM specification will be included in the returned mask. + * {@inheritDoc} + *

+ * Only the {@linkplain Modifier#fieldModifiers() field flags} specified in the JVM + * specification will be included in the returned mask. */ int getModifiers(); @@ -53,7 +54,7 @@ * Gets the constant value of this field. Note that a {@code static final} field may not be * considered constant if its declaring class is not yet initialized or if it is a well known * field that can be updated via other means (e.g., {@link System#setOut(java.io.PrintStream)}). - * + * * @param receiver object from which this field's value is to be read. This value is ignored if * this field is static. * @return the constant value of this field or {@code null} if this field is not considered @@ -65,7 +66,7 @@ * Gets the current value of this field for a given object, if available. There is no guarantee * that the same value will be returned by this method for a field unless the field is * considered to be {@linkplain #readConstantValue(Constant) constant} by the runtime. - * + * * @param receiver object from which this field's value is to be read. This value is ignored if * this field is static. * @return the value of this field or {@code null} if the value is not available (e.g., because @@ -82,7 +83,7 @@ /** * Returns the annotation for the specified type of this field, if such an annotation is * present. - * + * * @param annotationClass the Class object corresponding to the annotation type * @return this element's annotation for the specified annotation type if present on this field, * else {@code null} diff -r 3dde8d8c95b8 -r 40d0022115ee 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 Fri Apr 25 16:21:07 2014 +0200 +++ b/graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/ResolvedJavaMethod.java Mon Apr 28 11:18:15 2014 +0200 @@ -29,16 +29,16 @@ * Represents a resolved Java method. Methods, like fields and types, are resolved through * {@link ConstantPool constant pools}. */ -public interface ResolvedJavaMethod extends JavaMethod, InvokeTarget { +public interface ResolvedJavaMethod extends JavaMethod, InvokeTarget, ModifiersProvider { /** * Returns the bytecode of this method, if the method has code. The returned byte array does not * contain breakpoints or non-Java bytecodes. This may return null if the * {@link #getDeclaringClass() holder} is not {@link ResolvedJavaType#isLinked() linked}. - * + * * The contained constant pool indices may not be the ones found in the original class file but * they can be used with the Graal API (e.g. methods in {@link ConstantPool}). - * + * * @return the bytecode of the method, or {@code null} if {@code getCodeSize() == 0} or if the * code is not ready. */ @@ -47,7 +47,7 @@ /** * Returns the size of the bytecode of this method, if the method has code. This is equivalent * to {@link #getCode()}. {@code length} if the method has code. - * + * * @return the size of the bytecode in bytes, or 0 if no bytecode is available */ int getCodeSize(); @@ -69,10 +69,10 @@ int getMaxStackSize(); /** - * Returns the Java language modifiers for this method, as an integer. The {@link Modifier} - * class should be used to decode the modifiers. Only the - * {@linkplain Modifier#methodModifiers() method flags} specified in the JVM specification will - * be included in the returned mask. + * {@inheritDoc} + *

+ * Only the {@linkplain Modifier#methodModifiers() method flags} specified in the JVM + * specification will be included in the returned mask. */ int getModifiers(); @@ -84,10 +84,10 @@ /** * Returns {@code true} if this method is a default method; returns {@code false} otherwise. - * + * * A default method is a public non-abstract instance method, that is, a non-static method with * a body, declared in an interface type. - * + * * @return true if and only if this method is a default method as defined by the Java Language * Specification. */ @@ -95,22 +95,22 @@ /** * Checks whether this method is a class initializer. - * + * * @return {@code true} if the method is a class initializer */ boolean isClassInitializer(); /** * Checks whether this method is a constructor. - * + * * @return {@code true} if the method is a constructor */ boolean isConstructor(); /** * Checks whether this method can be statically bound (usually, that means it is final or - * private or static, but not abstract). - * + * private or static, but not abstract, or the declaring class is final) + * * @return {@code true} if this method can be statically bound */ boolean canBeStaticallyBound(); @@ -143,7 +143,7 @@ /** * Returns the annotation for the specified type of this method, if such an annotation is * present. - * + * * @param annotationClass the Class object corresponding to the annotation type * @return this element's annotation for the specified annotation type if present on this * method, else {@code null} @@ -153,7 +153,7 @@ /** * Returns an array of arrays that represent the annotations on the formal parameters, in * declaration order, of this method. - * + * * @see Method#getParameterAnnotations() */ Annotation[][] getParameterAnnotations(); @@ -161,7 +161,7 @@ /** * Returns an array of {@link Type} objects that represent the formal parameter types, in * declaration order, of this method. - * + * * @see Method#getGenericParameterTypes() */ Type[] getGenericParameterTypes(); @@ -192,7 +192,7 @@ * Invokes the underlying method represented by this object, on the specified object with the * specified parameters. This method is similar to a reflective method invocation by * {@link Method#invoke}. - * + * * @param receiver The receiver for the invocation, or {@code null} if it is a static method. * @param arguments The arguments for the invocation. * @return The value returned by the method invocation, or {@code null} if the return type is @@ -204,7 +204,7 @@ * Uses the constructor represented by this object to create and initialize a new instance of * the constructor's declaring class, with the specified initialization parameters. This method * is similar to a reflective instantiation by {@link Constructor#newInstance}. - * + * * @param arguments The arguments for the constructor. * @return The newly created and initialized object. */ @@ -212,14 +212,14 @@ /** * Gets the encoding of (that is, a constant representing the value of) this method. - * + * * @return a constant representing a reference to this method */ Constant getEncoding(); /** * Checks if this method is present in the virtual table. - * + * * @return true is this method is present in the virtual table */ boolean isInVirtualMethodTable(); diff -r 3dde8d8c95b8 -r 40d0022115ee 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 Fri Apr 25 16:21:07 2014 +0200 +++ b/graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/ResolvedJavaType.java Mon Apr 28 11:18:15 2014 +0200 @@ -31,7 +31,7 @@ * thereof. Types, like fields and methods, are resolved through {@link ConstantPool constant pools} * . */ -public interface ResolvedJavaType extends JavaType { +public interface ResolvedJavaType extends JavaType, ModifiersProvider { /** * Represents each of the several different parts of the runtime representation of a type which @@ -54,7 +54,7 @@ /** * Gets the encoding of (that is, a constant representing the value of) the specified part of * this type. - * + * * @param r the part of this type * @return a constant representing a reference to the specified part of this type */ @@ -62,7 +62,7 @@ /** * Checks whether this type has a finalizer method. - * + * * @return {@code true} if this class has a finalizer */ boolean hasFinalizer(); @@ -70,51 +70,52 @@ /** * Checks whether this type has any finalizable subclasses so far. Any decisions based on this * information require the registration of a dependency, since this information may change. - * + * * @return {@code true} if this class has any subclasses with finalizers */ boolean hasFinalizableSubclass(); /** * Checks whether this type is an interface. - * + * * @return {@code true} if this type is an interface */ boolean isInterface(); /** * Checks whether this type is an instance class. - * + * * @return {@code true} if this type is an instance class */ boolean isInstanceClass(); /** * Checks whether this type is an array class. - * + * * @return {@code true} if this type is an array class */ boolean isArray(); /** * Checks whether this type is primitive. - * + * * @return {@code true} if this type is primitive */ boolean isPrimitive(); /** - * Returns the Java language modifiers for this type, as an integer. The {@link Modifier} class - * should be used to decode the modifiers. Only the flags specified in the JVM specification - * will be included in the returned mask. This method is identical to - * {@link Class#getModifiers()} in terms of the value return for this type. + * {@inheritDoc} + *

+ * Only the flags specified in the JVM specification will be included in the returned mask. This + * method is identical to {@link Class#getModifiers()} in terms of the value return for this + * type. */ int getModifiers(); /** * Checks whether this type is initialized. If a type is initialized it implies that it was * {@link #isLinked() linked} and that the static initializer has run. - * + * * @return {@code true} if this type is initialized */ boolean isInitialized(); @@ -127,7 +128,7 @@ /** * Checks whether this type is linked and verified. When a type is linked the static initializer * has not necessarily run. An {@link #isInitialized() initialized} type is always linked. - * + * * @return {@code true} if this type is linked */ boolean isLinked(); @@ -141,7 +142,7 @@ /** * Checks whether the specified object is an instance of this type. - * + * * @param obj the object to test * @return {@code true} if the object is an instance of this type */ @@ -150,7 +151,7 @@ /** * Returns this type if it is an exact type otherwise returns null. This type is exact if it is * void, primitive, final, or an array of a final or primitive type. - * + * * @return this type if it is exact; {@code null} otherwise */ ResolvedJavaType asExactType(); @@ -172,7 +173,7 @@ /** * Walks the class hierarchy upwards and returns the least common class that is a superclass of * both the current and the given type. - * + * * @return the least common type that is a super type of both the current and the given type, or * {@code null} if primitive types are involved. */ @@ -194,7 +195,7 @@ *

* If the compiler uses the result of this method for its compilation, it must register an * assumption because dynamic class loading can invalidate the result of this method. - * + * * @return the unique concrete subclass for this type as described above */ ResolvedJavaType findUniqueConcreteSubtype(); @@ -208,7 +209,7 @@ * This resolution process only searches "up" the class hierarchy of this type. A broader search * that also walks "down" the hierarchy is implemented by * {@link #findUniqueConcreteMethod(ResolvedJavaMethod)}. - * + * * @param method the method to select the implementation of * @return the concrete method that would be selected at runtime, or {@code null} if there is no * concrete implementation of {@code method} in this type or any of its superclasses @@ -223,7 +224,7 @@ *

* If the compiler uses the result of this method for its compilation, it must register an * assumption because dynamic class loading can invalidate the result of this method. - * + * * @param method the method A for which a unique concrete target is searched * @return the unique concrete target or {@code null} if no such target exists or assumptions * are not supported by this runtime @@ -237,7 +238,7 @@ * is, for a single JVM execution the same order is returned each time this method is called. It * is also the "natural" order, which means that the JVM would expect the fields in this order * if no specific order is given. - * + * * @param includeSuperclasses if true, then instance fields for the complete hierarchy of this * type are included in the result * @return an array of instance fields @@ -247,7 +248,7 @@ /** * Returns the annotation for the specified type of this class, if such an annotation is * present. - * + * * @param annotationClass the Class object corresponding to the annotation type * @return this element's annotation for the specified annotation type if present on this class, * else {@code null} @@ -257,7 +258,7 @@ /** * Returns the instance field of this class (or one of its super classes) at the given offset, * or {@code null} if there is no such field. - * + * * @param offset the offset of the field to look for * @return the field with the given offset, or {@code null} if there is no such field. */ diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/Value.java --- a/graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/Value.java Fri Apr 25 16:21:07 2014 +0200 +++ b/graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/Value.java Mon Apr 28 11:18:15 2014 +0200 @@ -40,12 +40,30 @@ } }; + /** + * This is the Value of a node which was matched as part of a complex match. The value isn't + * actually useable but this marks it as having been evaluated. + */ + @SuppressWarnings("serial") public static Value INTERIOR_MATCH = new Value(Kind.Illegal) { + + @Override + public String toString() { + return "INTERIOR_MATCH"; + } + + @Override + public boolean equals(Object other) { + // This class is a singleton + return other != null && getClass() == other.getClass(); + } + }; + private final Kind kind; private final PlatformKind platformKind; /** * Initializes a new value of the specified kind. - * + * * @param platformKind the kind */ protected Value(PlatformKind platformKind) { diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.asm.amd64/src/com/oracle/graal/asm/amd64/AMD64Assembler.java --- a/graal/com.oracle.graal.asm.amd64/src/com/oracle/graal/asm/amd64/AMD64Assembler.java Fri Apr 25 16:21:07 2014 +0200 +++ b/graal/com.oracle.graal.asm.amd64/src/com/oracle/graal/asm/amd64/AMD64Assembler.java Mon Apr 28 11:18:15 2014 +0200 @@ -1647,9 +1647,14 @@ public final void shrl(Register dst, int imm8) { assert isShiftCount(imm8) : "illegal shift count"; int encode = prefixAndEncode(dst.encoding); - emitByte(0xC1); - emitByte(0xE8 | encode); - emitByte(imm8); + if (imm8 == 1) { + emitByte(0xD1); + emitByte(0xE8 | encode); + } else { + emitByte(0xC1); + emitByte(0xE8 | encode); + emitByte(imm8); + } } public final void shrl(Register dst) { @@ -1658,6 +1663,82 @@ emitByte(0xE8 | encode); } + public final void roll(Register dst, int imm8) { + assert isShiftCount(imm8) : "illegal shift count"; + int encode = prefixAndEncode(dst.encoding); + if (imm8 == 1) { + emitByte(0xD1); + emitByte(0xC0 | encode); + } else { + emitByte(0xC1); + emitByte(0xC0 | encode); + emitByte(imm8); + } + } + + public final void roll(Register dst) { + int encode = prefixAndEncode(dst.encoding); + emitByte(0xD3); + emitByte(0xC0 | encode); + } + + public final void rorl(Register dst, int imm8) { + assert isShiftCount(imm8) : "illegal shift count"; + int encode = prefixAndEncode(dst.encoding); + if (imm8 == 1) { + emitByte(0xD1); + emitByte(0xC8 | encode); + } else { + emitByte(0xC1); + emitByte(0xC8 | encode); + emitByte(imm8); + } + } + + public final void rorl(Register dst) { + int encode = prefixAndEncode(dst.encoding); + emitByte(0xD3); + emitByte(0xC8 | encode); + } + + public final void rolq(Register dst, int imm8) { + assert isShiftCount(imm8) : "illegal shift count"; + int encode = prefixqAndEncode(dst.encoding); + if (imm8 == 1) { + emitByte(0xD1); + emitByte(0xC0 | encode); + } else { + emitByte(0xC1); + emitByte(0xC0 | encode); + emitByte(imm8); + } + } + + public final void rolq(Register dst) { + int encode = prefixqAndEncode(dst.encoding); + emitByte(0xD3); + emitByte(0xC0 | encode); + } + + public final void rorq(Register dst, int imm8) { + assert isShiftCount(imm8) : "illegal shift count"; + int encode = prefixqAndEncode(dst.encoding); + if (imm8 == 1) { + emitByte(0xD1); + emitByte(0xC8 | encode); + } else { + emitByte(0xC1); + emitByte(0xC8 | encode); + emitByte(imm8); + } + } + + public final void rorq(Register dst) { + int encode = prefixqAndEncode(dst.encoding); + emitByte(0xD3); + emitByte(0xC8 | encode); + } + public final void sqrtsd(Register dst, AMD64Address src) { assert dst.getRegisterCategory() == AMD64.XMM; emitByte(0xF2); @@ -2442,9 +2523,14 @@ public final void shrq(Register dst, int imm8) { assert isShiftCount(imm8 >> 1) : "illegal shift count"; int encode = prefixqAndEncode(dst.encoding); - emitByte(0xC1); - emitByte(0xE8 | encode); - emitByte(imm8); + if (imm8 == 1) { + emitByte(0xD1); + emitByte(0xE8 | encode); + } else { + emitByte(0xC1); + emitByte(0xE8 | encode); + emitByte(imm8); + } } public final void shrq(Register dst) { @@ -2512,6 +2598,32 @@ emitInt(imm32); } + public final void xaddl(AMD64Address dst, Register src) { + prefix(dst, src); + emitByte(0x0F); + emitByte(0xC1); + emitOperandHelper(src, dst); + } + + public final void xaddq(AMD64Address dst, Register src) { + prefixq(dst, src); + emitByte(0x0F); + emitByte(0xC1); + emitOperandHelper(src, dst); + } + + public final void xchgl(Register dst, AMD64Address src) { + prefix(src, dst); + emitByte(0x87); + emitOperandHelper(dst, src); + } + + public final void xchgq(Register dst, AMD64Address src) { + prefixq(src, dst); + emitByte(0x87); + emitOperandHelper(dst, src); + } + public final void xorq(Register dst, int imm32) { emitArithImm32q(6, dst, imm32); } diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.asm.hsail/src/com/oracle/graal/asm/hsail/HSAILAssembler.java --- a/graal/com.oracle.graal.asm.hsail/src/com/oracle/graal/asm/hsail/HSAILAssembler.java Fri Apr 25 16:21:07 2014 +0200 +++ b/graal/com.oracle.graal.asm.hsail/src/com/oracle/graal/asm/hsail/HSAILAssembler.java Mon Apr 28 11:18:15 2014 +0200 @@ -27,7 +27,7 @@ import com.oracle.graal.api.code.*; import com.oracle.graal.api.meta.*; -import com.oracle.graal.graph.*; +import com.oracle.graal.compiler.common.*; import com.oracle.graal.hsail.*; /** @@ -542,10 +542,28 @@ * * @param result result operand that gets the original contents of the memory location * @param address the memory location - * @param deltaValue the amount to add + * @param delta the amount to add */ - public void emitAtomicAdd(AllocatableValue result, HSAILAddress address, Value deltaValue) { - emitString(String.format("atomic_add_global_u%d %s, %s, %s;", getArgSize(result), HSAIL.mapRegister(result), mapAddress(address), mapRegOrConstToString(deltaValue))); + public void emitAtomicAdd(AllocatableValue result, HSAILAddress address, Value delta) { + // ensure result and delta agree (this should probably be at some higher level) + Value mydelta = delta; + if (!isConstant(delta) && (getArgSize(result) != getArgSize(delta))) { + emitConvert(result, delta, result.getKind(), delta.getKind()); + mydelta = result; + } + String prefix = getArgTypeForceUnsigned(result); + emitString(String.format("atomic_add_global_%s %s, %s, %s;", prefix, HSAIL.mapRegister(result), mapAddress(address), mapRegOrConstToString(mydelta))); + } + + /** + * Emits an atomic_exch_global instruction. + * + * @param result result operand that gets the original contents of the memory location + * @param address the memory location + * @param newValue the new value to write to the memory location + */ + public void emitAtomicExch(Kind accessKind, AllocatableValue result, HSAILAddress address, Value newValue) { + emitString(String.format("atomic_exch_global_b%d %s, %s, %s;", getArgSizeFromKind(accessKind), HSAIL.mapRegister(result), mapAddress(address), mapRegOrConstToString(newValue))); } /** diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.asm.ptx/src/com/oracle/graal/asm/ptx/PTXAssembler.java --- a/graal/com.oracle.graal.asm.ptx/src/com/oracle/graal/asm/ptx/PTXAssembler.java Fri Apr 25 16:21:07 2014 +0200 +++ b/graal/com.oracle.graal.asm.ptx/src/com/oracle/graal/asm/ptx/PTXAssembler.java Mon Apr 28 11:18:15 2014 +0200 @@ -27,9 +27,9 @@ import com.oracle.graal.api.code.*; import com.oracle.graal.api.meta.*; import com.oracle.graal.asm.*; -import com.oracle.graal.graph.*; +import com.oracle.graal.compiler.common.*; +import com.oracle.graal.compiler.common.calc.*; import com.oracle.graal.lir.*; -import com.oracle.graal.nodes.calc.*; public class PTXAssembler extends AbstractPTXAssembler { diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.asm.ptx/src/com/oracle/graal/asm/ptx/PTXMacroAssembler.java --- a/graal/com.oracle.graal.asm.ptx/src/com/oracle/graal/asm/ptx/PTXMacroAssembler.java Fri Apr 25 16:21:07 2014 +0200 +++ b/graal/com.oracle.graal.asm.ptx/src/com/oracle/graal/asm/ptx/PTXMacroAssembler.java Mon Apr 28 11:18:15 2014 +0200 @@ -26,7 +26,7 @@ import com.oracle.graal.api.code.*; import com.oracle.graal.api.meta.*; -import com.oracle.graal.graph.*; +import com.oracle.graal.compiler.common.*; import com.oracle.graal.lir.*; public class PTXMacroAssembler extends PTXAssembler { diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.asm.sparc/src/com/oracle/graal/asm/sparc/SPARCAddress.java --- a/graal/com.oracle.graal.asm.sparc/src/com/oracle/graal/asm/sparc/SPARCAddress.java Fri Apr 25 16:21:07 2014 +0200 +++ b/graal/com.oracle.graal.asm.sparc/src/com/oracle/graal/asm/sparc/SPARCAddress.java Mon Apr 28 11:18:15 2014 +0200 @@ -25,16 +25,11 @@ import static com.oracle.graal.sparc.SPARC.*; import com.oracle.graal.api.code.*; -import com.oracle.graal.graph.*; +import com.oracle.graal.compiler.common.*; import com.oracle.graal.sparc.*; public class SPARCAddress extends AbstractAddress { - /** - * Stack bias for stack and frame pointer loads. - */ - private static final int STACK_BIAS = 0x7ff; - private final Register base; private final Register index; private final int displacement; @@ -42,7 +37,7 @@ /** * Creates an {@link SPARCAddress} with given base register, no scaling and a given * displacement. - * + * * @param base the base register * @param displacement the displacement */ @@ -54,7 +49,7 @@ /** * Creates an {@link SPARCAddress} with given base register, no scaling and a given index. - * + * * @param base the base register * @param index the index register */ @@ -113,7 +108,7 @@ /** * This method adds the stack-bias to the displacement if the base register is either * {@link SPARC#sp} or {@link SPARC#fp}. - * + * * @return Optional additive displacement. */ public int getDisplacement() { diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.asm.sparc/src/com/oracle/graal/asm/sparc/SPARCAssembler.java --- a/graal/com.oracle.graal.asm.sparc/src/com/oracle/graal/asm/sparc/SPARCAssembler.java Fri Apr 25 16:21:07 2014 +0200 +++ b/graal/com.oracle.graal.asm.sparc/src/com/oracle/graal/asm/sparc/SPARCAssembler.java Mon Apr 28 11:18:15 2014 +0200 @@ -37,7 +37,7 @@ /** * Constructs an assembler for the SPARC architecture. - * + * * @param registerConfig the register configuration used to bind {@link Register#Frame} and * {@link Register#CallerFrame} to physical registers. This value can be null if this * assembler instance will not be used to assemble instructions using these logical @@ -50,7 +50,7 @@ // @formatter:off /** * Instruction format for sethi. - * + * * | 00 | rd | op2 | imm22 | * |31 30|29 25|24 22|21 0| */ @@ -123,7 +123,7 @@ // @formatter:off /** * Instruction format for branches. - * + * * | 00 |a | cond | op2 | disp22 | * |31 30|29|28 25|24 22|21 0| */ @@ -142,7 +142,7 @@ // @formatter:off /** * Instruction format for conditional branches. - * + * * | 00 |a | cond | op2 |cc1|cc0|p | disp19 | * |31 30|29|28 25|24 22|21 |20 |19| 0| */ @@ -330,7 +330,7 @@ // @formatter:off /** * Instruction format for calls. - * + * * | 01 | disp30 | * |31 30|29 0| */ @@ -457,7 +457,7 @@ // @formatter:off /** * Instruction format for Arithmetic, Logical, Moves, Tcc, Prefetch, and Misc. - * + * * | 10 | rd | op3 | rs1 | i| imm_asi | rs2 | * | 10 | rd | op3 | rs1 | i| simm13 | * | 10 | rd | op3 | rs1 | i| x| | rs2 | @@ -594,7 +594,7 @@ // @formatter:off /** * Instruction format for Loads, Stores and Misc. - * + * * | 11 | rd | op3 | rs1 | i| imm_asi | rs2 | * | 11 | rd | op3 | rs1 | i| simm13 | * |31 30|29 25|24 19|18 14|13|12 5|4 0| @@ -749,7 +749,7 @@ // @formatter:off /** * Instruction format for Movcc. - * + * * | 10 | rd | op3 |cc2| cond | i|cc1|cc0| - | rs2 | * | 10 | rd | op3 |cc2| cond | i|cc1|cc0| simm11 | * |31 30|29 25|24 19| 18|17 14|13| 12| 11|10 5|4 0| @@ -1007,7 +1007,7 @@ Wrreg(0x30, "wrreg"), Saved(0x31, "saved"), - Fpop1(0x34, "fpop1"), + Fpop1(0b11_0100, "fpop1"), Fpop2(0x35, "fpop2"), Impdep1(0x36, "impdep1"), Impdep2(0x37, "impdep2"), @@ -1036,14 +1036,14 @@ Ldx(0b001011, "ldx"), Stx(0b001110, "stx"), - Ldf(0x20, "ldf"), + Ldf(0b100000, "ldf"), Ldfsr(0x21, "ldfsr"), Ldaf(0x22, "ldaf"), - Lddf(0x23, "lddf"), - Stf(0x24, "stf"), + Lddf(0b100011, "lddf"), + Stf(0b100100, "stf"), Stfsr(0x25, "stfsr"), Staf(0x26, "staf"), - Stdf(0x27, "stdf"); + Stdf(0b100111, "stdf"); // @formatter:on @@ -1092,9 +1092,9 @@ public enum Opfs { // @formatter:off - Fmovs(0x01, "fmovs"), - Fmovd(0x02, "fmovd"), - Fmovq(0x03, "fmovq"), + Fmovs(0b0_0000_0001, "fmovs"), + Fmovd(0b0_0000_0010, "fmovd"), + Fmovq(0b0_0000_0011, "fmovq"), Fnegs(0x05, "fnegs"), Fnegd(0x06, "fnegd"), Fnegq(0x07, "fnegq"), @@ -2376,6 +2376,20 @@ } } + public static class Fmovs extends Fmt3p { + + public Fmovs(Register src, Register dst) { + super(Ops.ArithOp, Op3s.Fpop1, Opfs.Fmovs, g0, src, dst); + } + } + + public static class Fmovd extends Fmt3p { + + public Fmovd(Register src, Register dst) { + super(Ops.ArithOp, Op3s.Fpop1, Opfs.Fmovd, g0, src, dst); + } + } + public static class Fmuls extends Fmt3p { public Fmuls(Register src1, Register src2, Register dst) { @@ -3174,6 +3188,20 @@ } } + public static class Stdf extends Fmt11 { + + public Stdf(Register dst, SPARCAddress src) { + super(Op3s.Stdf, src, dst); + } + } + + public static class Stf extends Fmt11 { + + public Stf(Register dst, SPARCAddress src) { + super(Op3s.Stf, src, dst); + } + } + public static class Sth extends Fmt11 { public Sth(Register dst, SPARCAddress addr) { diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.asm.test/src/com/oracle/graal/asm/test/AssemblerTest.java --- a/graal/com.oracle.graal.asm.test/src/com/oracle/graal/asm/test/AssemblerTest.java Fri Apr 25 16:21:07 2014 +0200 +++ b/graal/com.oracle.graal.asm.test/src/com/oracle/graal/asm/test/AssemblerTest.java Mon Apr 28 11:18:15 2014 +0200 @@ -61,7 +61,7 @@ byte[] targetCode = test.generateCode(compResult, codeCache.getTarget(), registerConfig, cc); compResult.setTargetCode(targetCode, targetCode.length); - InstalledCode code = codeCache.addMethod(method, compResult, null); + InstalledCode code = codeCache.addMethod(method, compResult, null, null); DisassemblerProvider dis = Graal.getRequiredCapability(RuntimeProvider.class).getHostBackend().getDisassembler(); if (dis != null) { diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.baseline/src/com/oracle/graal/baseline/BaselineBytecodeParser.java --- a/graal/com.oracle.graal.baseline/src/com/oracle/graal/baseline/BaselineBytecodeParser.java Fri Apr 25 16:21:07 2014 +0200 +++ b/graal/com.oracle.graal.baseline/src/com/oracle/graal/baseline/BaselineBytecodeParser.java Mon Apr 28 11:18:15 2014 +0200 @@ -22,8 +22,7 @@ */ package com.oracle.graal.baseline; -import static com.oracle.graal.phases.GraalOptions.*; -import static java.lang.reflect.Modifier.*; +import static com.oracle.graal.compiler.common.GraalOptions.*; import java.util.*; @@ -33,31 +32,32 @@ import com.oracle.graal.api.meta.ResolvedJavaType.Representation; import com.oracle.graal.bytecode.*; import com.oracle.graal.compiler.alloc.*; +import com.oracle.graal.compiler.common.*; +import com.oracle.graal.compiler.common.calc.*; +import com.oracle.graal.compiler.common.cfg.*; import com.oracle.graal.compiler.gen.*; import com.oracle.graal.compiler.target.*; import com.oracle.graal.debug.*; import com.oracle.graal.debug.Debug.Scope; -import com.oracle.graal.graph.*; import com.oracle.graal.java.*; import com.oracle.graal.java.BciBlockMapping.BciBlock; import com.oracle.graal.java.BciBlockMapping.LocalLiveness; import com.oracle.graal.lir.*; -import com.oracle.graal.lir.StandardOp.*; -import com.oracle.graal.nodes.calc.*; -import com.oracle.graal.nodes.calc.FloatConvertNode.FloatConvert; +import com.oracle.graal.lir.StandardOp.BlockEndOp; +import com.oracle.graal.lir.gen.*; import com.oracle.graal.nodes.cfg.*; import com.oracle.graal.phases.*; -public class BaselineBytecodeParser extends AbstractBytecodeParser implements BytecodeParserTool { +public class BaselineBytecodeParser extends AbstractBytecodeParser implements BytecodeParserTool { private Backend backend; - protected LIRGenerator gen; + protected LIRGeneratorTool gen; private LIRGenerationResult lirGenRes; private BytecodeLIRBuilder lirBuilder; @SuppressWarnings("unused") private BciBlock[] loopHeaders; private LocalLiveness liveness; private BciBlockBitMap blockVisited; - private class BciBlockBitMap { + private static class BciBlockBitMap { BitSet bitSet; public BciBlockBitMap(BciBlockMapping blockMap) { @@ -74,7 +74,7 @@ } public BaselineBytecodeParser(MetaAccessProvider metaAccess, ResolvedJavaMethod method, GraphBuilderConfiguration graphBuilderConfig, OptimisticOptimizations optimisticOpts, - LIRFrameStateBuilder frameState, BytecodeStream stream, ProfilingInfo profilingInfo, ConstantPool constantPool, int entryBCI, Backend backend) { + BaselineFrameStateBuilder frameState, BytecodeStream stream, ProfilingInfo profilingInfo, ConstantPool constantPool, int entryBCI, Backend backend) { super(metaAccess, method, graphBuilderConfig, optimisticOpts, frameState, stream, profilingInfo, constantPool, entryBCI); this.backend = backend; @@ -105,11 +105,11 @@ } } - if (isSynchronized(method.getModifiers())) { + if (method.isSynchronized()) { throw GraalInternalError.unimplemented("Handle synchronized methods"); } - frameState = new LIRFrameStateBuilder(method); + frameState = new BaselineFrameStateBuilder(method); frameState.clearNonLiveLocals(blockMap.startBlock, liveness, true); currentBlock = blockMap.startBlock; @@ -121,7 +121,7 @@ // add loops ? how do we add looks when we haven't parsed the bytecode? // create the control flow graph - LIRControlFlowGraph cfg = new LIRControlFlowGraph(blockMap.blocks.toArray(new BciBlock[0]), new Loop[0]); + BaselineControlFlowGraph cfg = new BaselineControlFlowGraph(blockMap); BlocksToDoubles blockProbabilities = new BlocksToDoubles(blockMap.blocks.size()); for (BciBlock b : blockMap.blocks) { @@ -261,8 +261,7 @@ @Override protected Value genIntegerMul(Kind kind, Value x, Value y) { - // TODO Auto-generated method stub - throw GraalInternalError.unimplemented("Auto-generated method stub"); + return gen.emitMul(x, y); } @Override @@ -584,9 +583,9 @@ return v; } - private void createTarget(BciBlock block, LIRFrameStateBuilder state) { - assert block != null && state != null; - assert !block.isExceptionEntry || state.stackSize() == 1; + private void createTarget(BciBlock block) { + assert block != null && frameState != null; + assert !block.isExceptionEntry || frameState.stackSize() == 1; if (!blockVisited.get(block)) { /* @@ -594,7 +593,14 @@ * placeholder that later can be replaced with a MergeNode when we see this block again. */ blockVisited.set(block); - block.entryState = state.copy(); + if (block.getPredecessorCount() > 1) { + /* + * If there are more than one predecessors we have to ensure that we are not passing + * constants to the new framestate otherwise we will get interfacing problems. + */ + moveConstantsToVariables(); + } + block.entryState = frameState.copy(); block.entryState.clearNonLiveLocals(block, liveness, true); Debug.log("createTarget %s: first visit", block); @@ -602,12 +608,17 @@ } // We already saw this block before, so we have to merge states. - if (!((LIRFrameStateBuilder) block.entryState).isCompatibleWith(state)) { + if (!((BaselineFrameStateBuilder) block.entryState).isCompatibleWith(frameState)) { throw new BailoutException("stacks do not match; bytecodes would not verify"); } if (block.isLoopHeader) { - assert currentBlock.getId() >= block.getId() : "must be backward branch"; + assert currentBlock == null || currentBlock.getId() >= block.getId() : "must be backward branch"; + if (currentBlock != null && currentBlock.numNormalSuccessors() == 1) { + // this is the only successor of the current block so we can adjust + adaptFramestate((BaselineFrameStateBuilder) block.entryState); + return; + } GraalInternalError.unimplemented("Loops not yet supported"); } assert currentBlock == null || currentBlock.getId() < block.getId() : "must not be backward branch"; @@ -619,7 +630,7 @@ */ if (currentBlock != null && currentBlock.numNormalSuccessors() == 1) { // this is the only successor of the current block so we can adjust - adaptFramestate((LIRFrameStateBuilder) block.entryState); + adaptFramestate((BaselineFrameStateBuilder) block.entryState); return; } GraalInternalError.unimplemented("second block visit not yet implemented"); @@ -629,35 +640,59 @@ Debug.log("createTarget %s: merging state", block); } - private void adaptValues(Value dst, Value src) { + private void moveConstantsToVariables() { + Debug.log("moveConstantsToVariables: framestate before: %s", frameState); + for (int i = 0; i < frameState.stackSize(); i++) { + Value src = frameState.stackAt(i); + if (src instanceof Constant) { + AllocatableValue dst = gen.newVariable(src.getPlatformKind()); + gen.emitMove(dst, src); + frameState.storeStack(i, dst); + Debug.log("introduce new variabe %s for stackslot %d (end of block %s", dst, i, currentBlock); + } + } + for (int i = 0; i < frameState.localsSize(); i++) { + Value src = frameState.localAt(i); + if (src instanceof Constant) { + AllocatableValue dst = gen.newVariable(src.getPlatformKind()); + gen.emitMove(dst, src); + frameState.storeLocal(i, dst); + Debug.log("introduce new variabe %s for local %d (end of block %s", dst, i, currentBlock); + } + } + Debug.log("moveConstantsToVariables: framestate after: %s", frameState); + } + + private static void adaptValues(Value dst, Value src, PhiResolver resolver) { if (dst == null) { return; } assert src != null : "Source is null but Destination is not!"; if (!dst.equals(src)) { - assert dst instanceof AllocatableValue; - gen.emitMove((AllocatableValue) dst, src); + resolver.move(dst, src); } } - private void adaptFramestate(LIRFrameStateBuilder other) { + private void adaptFramestate(BaselineFrameStateBuilder other) { assert frameState.isCompatibleWith(other) : "framestates not compatible!"; + PhiResolver resolver = new PhiResolver(gen); for (int i = 0; i < frameState.stackSize(); i++) { Value src = frameState.stackAt(i); Value dst = other.stackAt(i); - adaptValues(dst, src); + adaptValues(dst, src, resolver); } for (int i = 0; i < frameState.localsSize(); i++) { Value src = frameState.localAt(i); Value dst = other.localAt(i); - adaptValues(dst, src); + adaptValues(dst, src, resolver); } + resolver.dispose(); } @Override protected void processBlock(BciBlock block) { - frameState = (LIRFrameStateBuilder) block.entryState; + frameState = (BaselineFrameStateBuilder) block.entryState; setCurrentFrameState(frameState); currentBlock = block; iterateBytecodesForBlock(block); @@ -682,6 +717,14 @@ assert block.getPredecessorCount() > 0; } + if (block.isLoopHeader) { + /* + * We need to preserve the frame state builder of the loop header so that we can merge + * values for phi functions, so make a copy of it. + */ + block.entryState = frameState.copy(); + + } int endBCI = stream.endBCI(); stream.setBCI(block.startBci); @@ -725,7 +768,7 @@ } LabelRef getSuccessor(int index) { - createTarget(currentBlock.getSuccessor(index), frameState); + createTarget(currentBlock.getSuccessor(index)); return LabelRef.forSuccessor(lirGenRes.getLIR(), currentBlock, index); } diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.baseline/src/com/oracle/graal/baseline/BaselineCompiler.java --- a/graal/com.oracle.graal.baseline/src/com/oracle/graal/baseline/BaselineCompiler.java Fri Apr 25 16:21:07 2014 +0200 +++ b/graal/com.oracle.graal.baseline/src/com/oracle/graal/baseline/BaselineCompiler.java Mon Apr 28 11:18:15 2014 +0200 @@ -22,7 +22,7 @@ */ package com.oracle.graal.baseline; -import static com.oracle.graal.phases.GraalOptions.*; +import static com.oracle.graal.compiler.common.GraalOptions.*; import com.oracle.graal.api.code.*; import com.oracle.graal.api.meta.*; @@ -57,7 +57,7 @@ ConstantPool constantPool = method.getConstantPool(); TTY.Filter filter = new TTY.Filter(PrintFilter.getValue(), method); - LIRFrameStateBuilder frameState = new LIRFrameStateBuilder(method); + BaselineFrameStateBuilder frameState = new BaselineFrameStateBuilder(method); BaselineBytecodeParser parser = new BaselineBytecodeParser(metaAccess, method, graphBuilderConfig, optimisticOpts, frameState, stream, profilingInfo, constantPool, entryBCI, backend); diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.baseline/src/com/oracle/graal/baseline/BaselineControlFlowGraph.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.baseline/src/com/oracle/graal/baseline/BaselineControlFlowGraph.java Mon Apr 28 11:18:15 2014 +0200 @@ -0,0 +1,99 @@ +/* + * Copyright (c) 2014, 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.graal.baseline; + +import java.util.*; + +import com.oracle.graal.compiler.common.*; +import com.oracle.graal.compiler.common.cfg.*; +import com.oracle.graal.java.*; +import com.oracle.graal.java.BciBlockMapping.BciBlock; + +public class BaselineControlFlowGraph implements AbstractControlFlowGraph { + + private BciBlock[] blocks; + private Collection> loops; + private BitSet visited; + + public BaselineControlFlowGraph(BciBlockMapping blockMap) { + blocks = blockMap.blocks.toArray(new BciBlock[0]); + loops = new ArrayList<>(); + computeLoopInformation(); + } + + public BciBlock[] getBlocks() { + return blocks; + } + + public Collection> getLoops() { + return loops; + } + + public BciBlock getStartBlock() { + if (blocks.length > 0) { + return blocks[0]; + } + return null; + } + + private void computeLoopInformation() { + visited = new BitSet(blocks.length); + Deque stack = new ArrayDeque<>(); + for (int i = blocks.length - 1; i >= 0; i--) { + BciBlock block = blocks[i]; + calcLoop(block, stack); + } + } + + private void calcLoop(BciBlock block, Deque stack) { + if (visited.get(block.getId())) { + return; + } + visited.set(block.getId()); + if (block.isLoopEnd()) { + BciBlock loopHeader = getLoopHeader(block); + BaselineLoop l = new BaselineLoop(stack.peek(), loops.size(), loopHeader); + loops.add(l); + stack.push(l); + } + block.loop = stack.peek(); + if (block.isLoopHeader()) { + assert block.loop.header.equals(block); + stack.pop(); + } + for (BciBlock pred : block.getPredecessors()) { + calcLoop(pred, stack); + } + } + + private static BciBlock getLoopHeader(BciBlock block) { + assert block.isLoopEnd(); + for (BciBlock sux : block.getSuccessors()) { + if (sux.isLoopHeader() && sux.getId() <= block.getId() && block.loops == sux.loops) { + return sux; + } + } + throw GraalInternalError.shouldNotReachHere("No loop header found for " + block); + } + +} diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.baseline/src/com/oracle/graal/baseline/BaselineFrameStateBuilder.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.baseline/src/com/oracle/graal/baseline/BaselineFrameStateBuilder.java Mon Apr 28 11:18:15 2014 +0200 @@ -0,0 +1,103 @@ +/* + * Copyright (c) 2014, 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package com.oracle.graal.baseline; + +import com.oracle.graal.api.meta.*; +import com.oracle.graal.java.*; + +public class BaselineFrameStateBuilder extends AbstractFrameStateBuilder { + + private static final Value[] EMPTY_ARRAY = new Value[0]; + + public BaselineFrameStateBuilder(ResolvedJavaMethod method) { + // we always need at least one stack slot (for exceptions) + super(method, new Value[method.getMaxLocals()], new Value[Math.max(1, method.getMaxStackSize())], EMPTY_ARRAY); + } + + protected BaselineFrameStateBuilder(BaselineFrameStateBuilder other) { + super(other); + } + + @Override + protected Value[] getEmtpyArray() { + return EMPTY_ARRAY; + } + + @Override + public String toString() { + StringBuilder sb = new StringBuilder(); + sb.append("[locals: ["); + for (int i = 0; i < locals.length; i++) { + sb.append(i == 0 ? "" : ",").append(locals[i] == null ? "_" : locals[i].toString()); + } + sb.append("] stack: ["); + for (int i = 0; i < stackSize; i++) { + sb.append(i == 0 ? "" : ",").append(stack[i] == null ? "_" : stack[i].toString()); + } + sb.append("] locks: ["); + for (int i = 0; i < lockedObjects.length; i++) { + sb.append(i == 0 ? "" : ",").append(lockedObjects[i].toString()); + } + sb.append("]"); + if (rethrowException) { + sb.append(" rethrowException"); + } + sb.append("]"); + return sb.toString(); + } + + @Override + public BaselineFrameStateBuilder copy() { + return new BaselineFrameStateBuilder(this); + } + + private static boolean isCompatible(Value x, Value y) { + if (x == null && y == null) { + return true; + } + if ((x == null || y == null) || (x.getKind() != y.getKind())) { + return false; + } + return true; + + } + + @Override + public boolean isCompatibleWith(BaselineFrameStateBuilder other) { + assert method.equals(other.method) && localsSize() == other.localsSize() : "Can only compare frame states of the same method"; + + if (stackSize() != other.stackSize()) { + return false; + } + for (int i = 0; i < stackSize(); i++) { + if (!isCompatible(stackAt(i), other.stackAt(i))) { + return false; + } + } + if (lockedObjects.length != other.lockedObjects.length) { + return false; + } + return true; + } +} diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.baseline/src/com/oracle/graal/baseline/BaselineLoop.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.baseline/src/com/oracle/graal/baseline/BaselineLoop.java Mon Apr 28 11:18:15 2014 +0200 @@ -0,0 +1,41 @@ +/* + * Copyright (c) 2014, 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package com.oracle.graal.baseline; + +import com.oracle.graal.compiler.common.cfg.*; +import com.oracle.graal.java.BciBlockMapping.BciBlock; + +public class BaselineLoop extends Loop { + + protected BaselineLoop(Loop parent, int index, BciBlock header) { + super(parent, index, header); + } + + @Override + public long numBackedges() { + // currently only loops with one backedge are supported + return 1; + } + +} diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.baseline/src/com/oracle/graal/baseline/LIRBlock.java --- a/graal/com.oracle.graal.baseline/src/com/oracle/graal/baseline/LIRBlock.java Fri Apr 25 16:21:07 2014 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,62 +0,0 @@ -/* - * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -package com.oracle.graal.baseline; - -import java.util.*; - -import com.oracle.graal.nodes.cfg.*; - -public class LIRBlock extends AbstractBlockBase { - - public LIRBlock(int id) { - this.id = id; - predecessors = Collections.emptyList(); - successors = Collections.emptyList(); - } - - public Loop getLoop() { - // TODO Auto-generated method stub - return null; - } - - public int getLoopDepth() { - // TODO Auto-generated method stub - return 0; - } - - public boolean isLoopEnd() { - // TODO Auto-generated method stub - return false; - } - - public boolean isLoopHeader() { - // TODO Auto-generated method stub - return false; - } - - public boolean isExceptionEntry() { - // TODO Auto-generated method stub - return false; - } - -} diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.baseline/src/com/oracle/graal/baseline/LIRControlFlowGraph.java --- a/graal/com.oracle.graal.baseline/src/com/oracle/graal/baseline/LIRControlFlowGraph.java Fri Apr 25 16:21:07 2014 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,53 +0,0 @@ -/* - * Copyright (c) 2014, 2014, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -package com.oracle.graal.baseline; - -import com.oracle.graal.java.BciBlockMapping.BciBlock; -import com.oracle.graal.nodes.cfg.*; - -public class LIRControlFlowGraph implements AbstractControlFlowGraph { - - private BciBlock[] blocks; - private Loop[] loops; - - public LIRControlFlowGraph(BciBlock[] blocks, Loop[] loops) { - this.blocks = blocks; - this.loops = loops; - } - - public BciBlock[] getBlocks() { - return blocks; - } - - public Loop[] getLoops() { - return loops; - } - - public BciBlock getStartBlock() { - if (blocks.length > 0) { - return blocks[0]; - } - return null; - } - -} diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.baseline/src/com/oracle/graal/baseline/LIRFrameStateBuilder.java --- a/graal/com.oracle.graal.baseline/src/com/oracle/graal/baseline/LIRFrameStateBuilder.java Fri Apr 25 16:21:07 2014 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,103 +0,0 @@ -/* - * Copyright (c) 2014, 2014, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -package com.oracle.graal.baseline; - -import com.oracle.graal.api.meta.*; -import com.oracle.graal.java.*; - -public class LIRFrameStateBuilder extends AbstractFrameStateBuilder { - - private static final Value[] EMPTY_ARRAY = new Value[0]; - - public LIRFrameStateBuilder(ResolvedJavaMethod method) { - // we always need at least one stack slot (for exceptions) - super(method, new Value[method.getMaxLocals()], new Value[Math.max(1, method.getMaxStackSize())], EMPTY_ARRAY); - } - - protected LIRFrameStateBuilder(LIRFrameStateBuilder other) { - super(other); - } - - @Override - protected Value[] getEmtpyArray() { - return EMPTY_ARRAY; - } - - @Override - public String toString() { - StringBuilder sb = new StringBuilder(); - sb.append("[locals: ["); - for (int i = 0; i < locals.length; i++) { - sb.append(i == 0 ? "" : ",").append(locals[i] == null ? "_" : locals[i].toString()); - } - sb.append("] stack: ["); - for (int i = 0; i < stackSize; i++) { - sb.append(i == 0 ? "" : ",").append(stack[i] == null ? "_" : stack[i].toString()); - } - sb.append("] locks: ["); - for (int i = 0; i < lockedObjects.length; i++) { - sb.append(i == 0 ? "" : ",").append(lockedObjects[i].toString()); - } - sb.append("]"); - if (rethrowException) { - sb.append(" rethrowException"); - } - sb.append("]"); - return sb.toString(); - } - - @Override - public LIRFrameStateBuilder copy() { - return new LIRFrameStateBuilder(this); - } - - private static boolean isCompatible(Value x, Value y) { - if (x == null && y == null) { - return true; - } - if ((x == null || y == null) || (x.getKind() != y.getKind())) { - return false; - } - return true; - - } - - @Override - public boolean isCompatibleWith(LIRFrameStateBuilder other) { - assert method.equals(other.method) && localsSize() == other.localsSize() : "Can only compare frame states of the same method"; - - if (stackSize() != other.stackSize()) { - return false; - } - for (int i = 0; i < stackSize(); i++) { - if (!isCompatible(stackAt(i), other.stackAt(i))) { - return false; - } - } - if (lockedObjects.length != other.lockedObjects.length) { - return false; - } - return true; - } -} diff -r 3dde8d8c95b8 -r 40d0022115ee 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 Fri Apr 25 16:21:07 2014 +0200 +++ b/graal/com.oracle.graal.compiler.amd64/src/com/oracle/graal/compiler/amd64/AMD64LIRGenerator.java Mon Apr 28 11:18:15 2014 +0200 @@ -35,8 +35,9 @@ import com.oracle.graal.asm.*; import com.oracle.graal.asm.amd64.AMD64Address.Scale; import com.oracle.graal.asm.amd64.AMD64Assembler.ConditionFlag; -import com.oracle.graal.compiler.gen.*; -import com.oracle.graal.graph.*; +import com.oracle.graal.compiler.common.*; +import com.oracle.graal.compiler.common.calc.*; +import com.oracle.graal.compiler.common.type.*; import com.oracle.graal.lir.*; import com.oracle.graal.lir.StandardOp.JumpOp; import com.oracle.graal.lir.amd64.*; @@ -51,6 +52,7 @@ import com.oracle.graal.lir.amd64.AMD64Arithmetic.Unary1Op; import com.oracle.graal.lir.amd64.AMD64Arithmetic.Unary2MemoryOp; import com.oracle.graal.lir.amd64.AMD64Arithmetic.Unary2Op; +import com.oracle.graal.lir.amd64.AMD64Arithmetic.Unary2RegOp; import com.oracle.graal.lir.amd64.AMD64Compare.CompareMemoryOp; import com.oracle.graal.lir.amd64.AMD64Compare.CompareOp; import com.oracle.graal.lir.amd64.AMD64ControlFlow.BranchOp; @@ -67,10 +69,7 @@ import com.oracle.graal.lir.amd64.AMD64Move.MoveToRegOp; import com.oracle.graal.lir.amd64.AMD64Move.StackLeaOp; import com.oracle.graal.lir.amd64.AMD64Move.ZeroExtendLoadOp; -import com.oracle.graal.nodes.*; -import com.oracle.graal.nodes.calc.*; -import com.oracle.graal.nodes.calc.FloatConvertNode.FloatConvert; -import com.oracle.graal.nodes.type.*; +import com.oracle.graal.lir.gen.*; import com.oracle.graal.phases.util.*; /** @@ -264,6 +263,25 @@ } } + public void emitCompareBranchMemory(Kind cmpKind, Value left, AMD64AddressValue right, LIRFrameState state, Condition cond, boolean unorderedIsTrue, LabelRef trueLabel, LabelRef falseLabel, + double trueLabelProbability) { + boolean mirrored = emitCompareMemory(cmpKind, left, right, state); + Condition finalCondition = mirrored ? cond.mirror() : cond; + switch (left.getKind().getStackKind()) { + case Int: + case Long: + case Object: + append(new BranchOp(finalCondition, trueLabel, falseLabel, trueLabelProbability)); + break; + case Float: + case Double: + append(new FloatBranchOp(finalCondition, unorderedIsTrue, trueLabel, falseLabel, trueLabelProbability)); + break; + default: + throw GraalInternalError.shouldNotReachHere("" + left.getKind()); + } + } + @Override public void emitOverflowCheckBranch(LabelRef overflow, LabelRef noOverflow, double overflowProbability) { append(new BranchOp(ConditionFlag.Overflow, overflow, noOverflow, overflowProbability)); @@ -344,6 +362,26 @@ } } + /** + * This method emits the compare against memory instruction, and may reorder the operands. It + * returns true if it did so. + * + * @param b the right operand of the comparison + * @return true if the left and right operands were switched, false otherwise + */ + private boolean emitCompareMemory(Kind cmpKind, Value a, AMD64AddressValue b, LIRFrameState state) { + boolean mirrored; + if (LIRValueUtil.isVariable(a)) { + Variable left = load(a); + emitCompareRegMemoryOp(cmpKind, left, b, state); + mirrored = false; + } else { + emitCompareMemoryConOp(cmpKind, b, a, state); + mirrored = true; + } + return mirrored; + } + protected void emitCompareMemoryConOp(Kind kind, AMD64AddressValue address, Value value, LIRFrameState state) { assert kind.getStackKind() == value.getKind().getStackKind(); switch (kind) { @@ -589,8 +627,7 @@ append(new DivRemOp(op, rax, asAllocatable(b), state)); } - public Value[] emitIntegerDivRem(Value a, Value b, DeoptimizingNode deopting) { - LIRFrameState state = state(deopting); + public Value[] emitIntegerDivRem(Value a, Value b, LIRFrameState state) { switch (a.getKind().getStackKind()) { case Int: emitDivRem(IDIVREM, a, b, state); @@ -604,13 +641,13 @@ } @Override - public Value emitDiv(Value a, Value b, DeoptimizingNode deopting) { + public Value emitDiv(Value a, Value b, LIRFrameState state) { switch (a.getKind().getStackKind()) { case Int: - emitDivRem(IDIV, a, b, state(deopting)); + emitDivRem(IDIV, a, b, state); return emitMove(RAX_I); case Long: - emitDivRem(LDIV, a, b, state(deopting)); + emitDivRem(LDIV, a, b, state); return emitMove(RAX_L); case Float: { Variable result = newVariable(a.getPlatformKind()); @@ -628,13 +665,13 @@ } @Override - public Value emitRem(Value a, Value b, DeoptimizingNode deopting) { + public Value emitRem(Value a, Value b, LIRFrameState state) { switch (a.getKind().getStackKind()) { case Int: - emitDivRem(IREM, a, b, state(deopting)); + emitDivRem(IREM, a, b, state); return emitMove(RDX_I); case Long: - emitDivRem(LREM, a, b, state(deopting)); + emitDivRem(LREM, a, b, state); return emitMove(RDX_L); case Float: { Variable result = newVariable(a.getPlatformKind()); @@ -652,8 +689,7 @@ } @Override - public Variable emitUDiv(Value a, Value b, DeoptimizingNode deopting) { - LIRFrameState state = state(deopting); + public Variable emitUDiv(Value a, Value b, LIRFrameState state) { switch (a.getKind().getStackKind()) { case Int: emitDivRem(IUDIV, a, b, state); @@ -667,8 +703,7 @@ } @Override - public Variable emitURem(Value a, Value b, DeoptimizingNode deopting) { - LIRFrameState state = state(deopting); + public Variable emitURem(Value a, Value b, LIRFrameState state) { switch (a.getKind().getStackKind()) { case Int: emitDivRem(IUREM, a, b, state); @@ -765,9 +800,31 @@ } } - private AllocatableValue emitConvert1Op(PlatformKind kind, AMD64Arithmetic op, AllocatableValue input) { + public Variable emitRol(Value a, Value b) { + switch (a.getKind().getStackKind()) { + case Int: + return emitShift(IROL, a, b); + case Long: + return emitShift(LROL, a, b); + default: + throw GraalInternalError.shouldNotReachHere(); + } + } + + public Variable emitRor(Value a, Value b) { + switch (a.getKind().getStackKind()) { + case Int: + return emitShift(IROR, a, b); + case Long: + return emitShift(LROR, a, b); + default: + throw GraalInternalError.shouldNotReachHere(); + } + } + + private AllocatableValue emitConvert2RegOp(PlatformKind kind, AMD64Arithmetic op, AllocatableValue input) { Variable result = newVariable(kind); - append(new Unary1Op(op, result, input)); + append(new Unary2RegOp(op, result, input)); return result; } @@ -850,7 +907,7 @@ public Value emitNarrow(Value inputVal, int bits) { if (inputVal.getKind() == Kind.Long && bits <= 32) { // TODO make it possible to reinterpret Long as Int in LIR without move - return emitConvert1Op(Kind.Int, L2I, asAllocatable(inputVal)); + return emitConvert2RegOp(Kind.Int, L2I, asAllocatable(inputVal)); } else { return inputVal; } @@ -1020,7 +1077,7 @@ } @Override - protected void emitStrategySwitch(SwitchStrategy strategy, Variable key, LabelRef[] keyTargets, LabelRef defaultTarget) { + public void emitStrategySwitch(SwitchStrategy strategy, Variable key, LabelRef[] keyTargets, LabelRef defaultTarget) { // a temp is needed for loading object constants boolean needsTemp = key.getKind() == Kind.Object; append(new StrategySwitchOp(strategy, keyTargets, defaultTarget, key, needsTemp ? newVariable(key.getKind()) : Value.ILLEGAL)); diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.compiler.amd64/src/com/oracle/graal/compiler/amd64/AMD64MemoryPeephole.java --- a/graal/com.oracle.graal.compiler.amd64/src/com/oracle/graal/compiler/amd64/AMD64MemoryPeephole.java Fri Apr 25 16:21:07 2014 +0200 +++ b/graal/com.oracle.graal.compiler.amd64/src/com/oracle/graal/compiler/amd64/AMD64MemoryPeephole.java Mon Apr 28 11:18:15 2014 +0200 @@ -23,26 +23,26 @@ package com.oracle.graal.compiler.amd64; +import static com.oracle.graal.compiler.common.GraalOptions.*; import static com.oracle.graal.lir.amd64.AMD64Arithmetic.*; import static com.oracle.graal.nodes.ConstantNode.*; -import static com.oracle.graal.phases.GraalOptions.*; import java.util.*; import com.oracle.graal.api.meta.*; import com.oracle.graal.asm.*; +import com.oracle.graal.compiler.common.*; +import com.oracle.graal.compiler.common.calc.*; +import com.oracle.graal.compiler.common.type.*; import com.oracle.graal.debug.*; -import com.oracle.graal.graph.*; import com.oracle.graal.lir.*; import com.oracle.graal.lir.amd64.*; import com.oracle.graal.lir.amd64.AMD64ControlFlow.BranchOp; import com.oracle.graal.lir.amd64.AMD64ControlFlow.FloatBranchOp; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.calc.*; -import com.oracle.graal.nodes.calc.FloatConvertNode.FloatConvert; import com.oracle.graal.nodes.extended.*; import com.oracle.graal.nodes.spi.*; -import com.oracle.graal.nodes.type.*; public class AMD64MemoryPeephole implements MemoryArithmeticLIRLowerer { protected final AMD64NodeLIRBuilder gen; @@ -71,13 +71,17 @@ protected LIRFrameState getState(Access access) { if (access instanceof DeoptimizingNode) { - return gen.getLIRGenerator().state((DeoptimizingNode) access); + return gen.state((DeoptimizingNode) access); } return null; } + protected Kind getMemoryKind(Access access) { + return (Kind) gen.getLIRGeneratorTool().getPlatformKind(access.asNode().stamp()); + } + protected AMD64AddressValue makeAddress(Access access) { - return (AMD64AddressValue) access.accessLocation().generateAddress(gen, gen.operand(access.object())); + return (AMD64AddressValue) access.accessLocation().generateAddress(gen, gen.getLIRGeneratorTool(), gen.operand(access.object())); } protected Value emitBinaryMemory(AMD64Arithmetic op, boolean commutative, ValueNode x, ValueNode y, Access access) { @@ -90,7 +94,7 @@ } } ensureEvaluated(other); - return gen.getLIRGenerator().emitBinaryMemory(op, access.accessLocation().getValueKind(), gen.getLIRGeneratorTool().asAllocatable(gen.operand(other)), makeAddress(access), getState(access)); + return gen.getLIRGeneratorTool().emitBinaryMemory(op, getMemoryKind(access), gen.getLIRGeneratorTool().asAllocatable(gen.operand(other)), makeAddress(access), getState(access)); } /** @@ -124,12 +128,12 @@ AMD64AddressValue address = makeAddress(access); LIRFrameState state = getState(access); evaluateDeferred(); - return gen.getLIRGenerator().emitConvert2MemoryOp(kind, op, address, state); + return gen.getLIRGeneratorTool().emitConvert2MemoryOp(kind, op, address, state); } @Override public Value emitAddMemory(ValueNode x, ValueNode y, Access access) { - switch (access.accessLocation().getValueKind()) { + switch (getMemoryKind(access)) { case Int: return emitBinaryMemory(IADD, true, x, y, access); case Long: @@ -145,7 +149,7 @@ @Override public Value emitSubMemory(ValueNode x, ValueNode y, Access access) { - switch (access.accessLocation().getValueKind()) { + switch (getMemoryKind(access)) { case Int: return emitBinaryMemory(ISUB, false, x, y, access); case Long: @@ -161,7 +165,7 @@ @Override public Value emitMulMemory(ValueNode x, ValueNode y, Access access) { - switch (access.accessLocation().getValueKind()) { + switch (getMemoryKind(access)) { case Int: return emitBinaryMemory(IMUL, true, x, y, access); case Long: @@ -187,7 +191,7 @@ @Override public Value emitAndMemory(ValueNode x, ValueNode y, Access access) { - Kind kind = access.accessLocation().getValueKind(); + Kind kind = getMemoryKind(access); switch (kind) { case Int: return emitBinaryMemory(IAND, true, x, y, access); @@ -224,7 +228,7 @@ @Override public Value emitOrMemory(ValueNode x, ValueNode y, Access access) { - switch (access.accessLocation().getValueKind()) { + switch (getMemoryKind(access)) { case Int: return emitBinaryMemory(IOR, true, x, y, access); case Long: @@ -236,7 +240,7 @@ @Override public Value emitXorMemory(ValueNode x, ValueNode y, Access access) { - switch (access.accessLocation().getValueKind()) { + switch (getMemoryKind(access)) { case Int: return emitBinaryMemory(IXOR, true, x, y, access); case Long: @@ -248,8 +252,8 @@ @Override public Value emitReinterpretMemory(Stamp stamp, Access access) { - PlatformKind to = gen.getLIRGenerator().getPlatformKind(stamp); - Kind from = access.accessLocation().getValueKind(); + PlatformKind to = gen.getLIRGeneratorTool().getPlatformKind(stamp); + Kind from = getMemoryKind(access); assert to != from : "should have been eliminated"; /* @@ -355,7 +359,7 @@ @Override public Value emitZeroExtendMemory(int fromBits, int toBits, Access access) { assert fromBits != toBits; - Kind memoryKind = access.accessLocation().getValueKind(); + Kind memoryKind = getMemoryKind(access); if (memoryKind.getBitCount() != fromBits && !memoryKind.isUnsigned()) { // The memory being read from is signed and smaller than the result size so // this is a sign extension to inputBits followed by a zero extension to resultBits @@ -366,7 +370,7 @@ memoryKind = Kind.Char; } evaluateDeferred(); - return gen.getLIRGenerator().emitZeroExtendMemory(memoryKind, toBits, makeAddress(access), getState(access)); + return gen.getLIRGeneratorTool().emitZeroExtendMemory(memoryKind, toBits, makeAddress(access), getState(access)); } public boolean emitIfMemory(IfNode x, Access access) { @@ -399,7 +403,7 @@ private boolean emitIntegerTestBranchMemory(ValueNode left, ValueNode right, Access access, LabelRef trueLabel, LabelRef falseLabel, double trueLabelProbability) { ValueNode other = selectOtherInput(left, right, access); - Kind kind = access.accessLocation().getValueKind(); + Kind kind = getMemoryKind(access); if (other.isConstant()) { if (kind != kind.getStackKind()) { return false; @@ -439,7 +443,7 @@ protected boolean emitCompareBranchMemory(ValueNode left, ValueNode right, Access access, Condition cond, boolean unorderedIsTrue, LabelRef trueLabel, LabelRef falseLabel, double trueLabelProbability) { ValueNode other = selectOtherInput(left, right, access); - Kind kind = access.accessLocation().getValueKind(); + Kind kind = getMemoryKind(access); boolean mirrored = false; if (other.isConstant()) { @@ -459,7 +463,7 @@ } } ensureEvaluated(other); - gen.getLIRGenerator().emitCompareMemoryConOp(kind, makeAddress(access), constant, getState(access)); + gen.getLIRGeneratorTool().emitCompareMemoryConOp(kind, makeAddress(access), constant, getState(access)); mirrored = uncast(right) == access; } else { if (kind == Kind.Object) { @@ -469,7 +473,7 @@ } evaluateDeferred(); - gen.getLIRGenerator().emitCompareRegMemoryOp(kind, gen.operand(other), makeAddress(access), getState(access)); + gen.getLIRGeneratorTool().emitCompareRegMemoryOp(kind, gen.operand(other), makeAddress(access), getState(access)); mirrored = uncast(left) == access; } diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.compiler.amd64/src/com/oracle/graal/compiler/amd64/AMD64NodeLIRBuilder.java --- a/graal/com.oracle.graal.compiler.amd64/src/com/oracle/graal/compiler/amd64/AMD64NodeLIRBuilder.java Fri Apr 25 16:21:07 2014 +0200 +++ b/graal/com.oracle.graal.compiler.amd64/src/com/oracle/graal/compiler/amd64/AMD64NodeLIRBuilder.java Mon Apr 28 11:18:15 2014 +0200 @@ -23,19 +23,29 @@ package com.oracle.graal.compiler.amd64; +import static com.oracle.graal.lir.amd64.AMD64Arithmetic.*; + import com.oracle.graal.amd64.*; import com.oracle.graal.api.code.*; import com.oracle.graal.api.meta.*; +import com.oracle.graal.asm.*; +import com.oracle.graal.compiler.common.*; +import com.oracle.graal.compiler.common.calc.*; import com.oracle.graal.compiler.gen.*; +import com.oracle.graal.compiler.match.*; +import com.oracle.graal.debug.*; import com.oracle.graal.lir.*; import com.oracle.graal.lir.amd64.*; +import com.oracle.graal.lir.amd64.AMD64ControlFlow.BranchOp; +import com.oracle.graal.lir.gen.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.calc.*; +import com.oracle.graal.nodes.extended.*; import com.oracle.graal.nodes.spi.*; public abstract class AMD64NodeLIRBuilder extends NodeLIRBuilder { - public AMD64NodeLIRBuilder(StructuredGraph graph, LIRGenerator gen) { + public AMD64NodeLIRBuilder(StructuredGraph graph, LIRGeneratorTool gen) { super(graph, gen); } @@ -60,7 +70,7 @@ @Override public void emitNullCheck(ValueNode v, DeoptimizingNode deopt) { assert v.getKind() == Kind.Object : v + " - " + v.stamp() + " @ " + deopt; - append(new AMD64Move.NullCheckOp(gen.load(operand(v)), gen.state(deopt))); + append(new AMD64Move.NullCheckOp(gen.load(operand(v)), state(deopt))); } @Override @@ -73,7 +83,7 @@ if (((fixedWithNextNode instanceof IntegerDivNode) || (fixedWithNextNode instanceof IntegerRemNode)) && fixedWithNextNode.getClass() != divRem.getClass()) { FixedBinaryNode otherDivRem = (FixedBinaryNode) fixedWithNextNode; if (otherDivRem.x() == divRem.x() && otherDivRem.y() == divRem.y() && !hasOperand(otherDivRem)) { - Value[] results = ((AMD64LIRGenerator) gen).emitIntegerDivRem(operand(divRem.x()), operand(divRem.y()), (DeoptimizingNode) valueNode); + Value[] results = ((AMD64LIRGenerator) gen).emitIntegerDivRem(operand(divRem.x()), operand(divRem.y()), state((DeoptimizingNode) valueNode)); if (divRem instanceof IntegerDivNode) { setResult(divRem, results[0]); setResult(otherDivRem, results[1]); @@ -90,6 +100,525 @@ return false; } + protected LIRFrameState getState(Access access) { + if (access instanceof DeoptimizingNode) { + return state((DeoptimizingNode) access); + } + return null; + } + + protected Kind getMemoryKind(Access access) { + return (Kind) gen.getPlatformKind(access.asNode().stamp()); + } + + protected AMD64AddressValue makeAddress(Access access) { + return (AMD64AddressValue) access.accessLocation().generateAddress(this, gen, operand(access.object())); + } + + protected ValueNode uncast(ValueNode value) { + if (value instanceof UnsafeCastNode) { + UnsafeCastNode cast = (UnsafeCastNode) value; + return cast.getOriginalNode(); + } + return value; + } + + protected ComplexMatchResult emitCompareBranchMemory(IfNode ifNode, CompareNode compare, ValueNode value, Access access) { + Condition cond = compare.condition(); + Kind kind = getMemoryKind(access); + + if (value.isConstant()) { + Constant constant = value.asConstant(); + if (kind == Kind.Long && !NumUtil.isInt(constant.asLong())) { + // Only imm32 as long + return null; + } + if (kind.isNumericFloat()) { + Debug.log("Skipping constant compares for float kinds"); + return null; + } + if (kind == Kind.Object) { + if (!constant.isNull()) { + Debug.log("Skipping constant compares for Object kinds"); + return null; + } + } + } else { + if (kind == Kind.Object) { + // Can't compare against objects since they require encode/decode + Debug.log("Skipping compares for Object kinds"); + return null; + } + } + + PlatformKind cmpKind = gen.getPlatformKind(compare.x().stamp()); + if (cmpKind instanceof Kind) { + // emitCompareBranchMemory expects the memory on the right, so mirror the condition if + // that's not true. It might be mirrored again the actual compare is emitted but that's + // ok. + Condition finalCondition = uncast(compare.x()) == access ? cond.mirror() : cond; + return new ComplexMatchResult() { + public Value evaluate(NodeLIRBuilder builder) { + LabelRef trueLabel = getLIRBlock(ifNode.trueSuccessor()); + LabelRef falseLabel = getLIRBlock(ifNode.falseSuccessor()); + boolean unorderedIsTrue = compare.unorderedIsTrue(); + double trueLabelProbability = ifNode.probability(ifNode.trueSuccessor()); + Value other; + if (value.isConstant()) { + other = value.asConstant(); + } else { + other = operand(value); + } + + getLIRGeneratorTool().emitCompareBranchMemory((Kind) cmpKind, other, makeAddress(access), getState(access), finalCondition, unorderedIsTrue, trueLabel, falseLabel, + trueLabelProbability); + return null; + } + }; + } + return null; + + } + + private ComplexMatchResult emitIntegerTestBranchMemory(IfNode x, ValueNode value, Access access) { + LabelRef trueLabel = getLIRBlock(x.trueSuccessor()); + LabelRef falseLabel = getLIRBlock(x.falseSuccessor()); + double trueLabelProbability = x.probability(x.trueSuccessor()); + Kind kind = getMemoryKind(access); + if (value.isConstant()) { + if (kind != kind.getStackKind()) { + return null; + } + Constant constant = value.asConstant(); + if (kind == Kind.Long && !NumUtil.isInt(constant.asLong())) { + // Only imm32 as long + return null; + } + return new ComplexMatchResult() { + public Value evaluate(NodeLIRBuilder builder) { + gen.append(new AMD64TestMemoryOp(kind, makeAddress(access), constant, getState(access))); + gen.append(new BranchOp(Condition.EQ, trueLabel, falseLabel, trueLabelProbability)); + return null; + } + }; + } else { + return new ComplexMatchResult() { + public Value evaluate(NodeLIRBuilder builder) { + gen.append(new AMD64TestMemoryOp(kind, makeAddress(access), operand(value), getState(access))); + gen.append(new BranchOp(Condition.EQ, trueLabel, falseLabel, trueLabelProbability)); + return null; + } + }; + } + } + + protected Value emitConvert2MemoryOp(PlatformKind kind, AMD64Arithmetic op, Access access) { + AMD64AddressValue address = makeAddress(access); + LIRFrameState state = getState(access); + return getLIRGeneratorTool().emitConvert2MemoryOp(kind, op, address, state); + } + + private Value emitFloatConvertMemory(FloatConvertNode op, Access access) { + switch (op.getOp()) { + case D2F: + return emitConvert2MemoryOp(Kind.Float, D2F, access); + case D2I: + return emitConvert2MemoryOp(Kind.Int, D2I, access); + case D2L: + return emitConvert2MemoryOp(Kind.Long, D2L, access); + case F2D: + return emitConvert2MemoryOp(Kind.Double, F2D, access); + case F2I: + return emitConvert2MemoryOp(Kind.Int, F2I, access); + case F2L: + return emitConvert2MemoryOp(Kind.Long, F2L, access); + case I2D: + return emitConvert2MemoryOp(Kind.Double, I2D, access); + case I2F: + return emitConvert2MemoryOp(Kind.Float, I2F, access); + case L2D: + return emitConvert2MemoryOp(Kind.Double, L2D, access); + case L2F: + return emitConvert2MemoryOp(Kind.Float, L2F, access); + default: + throw GraalInternalError.shouldNotReachHere(); + } + } + + private ComplexMatchResult emitSignExtendMemory(Access access, int fromBits, int toBits) { + assert fromBits <= toBits && toBits <= 64; + Kind kind = null; + AMD64Arithmetic op = null; + if (fromBits == toBits) { + return null; + } else if (toBits > 32) { + kind = Kind.Long; + // sign extend to 64 bits + switch (fromBits) { + case 8: + op = B2L; + break; + case 16: + op = S2L; + break; + case 32: + op = I2L; + break; + default: + throw GraalInternalError.unimplemented("unsupported sign extension (" + fromBits + " bit -> " + toBits + " bit)"); + } + } else { + kind = Kind.Int; + // sign extend to 32 bits (smaller values are internally represented as 32 bit values) + switch (fromBits) { + case 8: + op = B2I; + break; + case 16: + op = S2I; + break; + case 32: + return null; + default: + throw GraalInternalError.unimplemented("unsupported sign extension (" + fromBits + " bit -> " + toBits + " bit)"); + } + } + if (kind != null && op != null) { + Kind localKind = kind; + AMD64Arithmetic localOp = op; + return new ComplexMatchResult() { + public Value evaluate(NodeLIRBuilder builder) { + return emitConvert2MemoryOp(localKind, localOp, access); + } + }; + } + return null; + } + + private Value emitReinterpretMemory(PlatformKind to, Access access) { + Kind from = getMemoryKind(access); + assert to != from : "should have been eliminated"; + + /* + * Conversions between integer to floating point types require moves between CPU and FPU + * registers. + */ + switch ((Kind) to) { + case Int: + switch (from) { + case Float: + return emitConvert2MemoryOp(to, MOV_F2I, access); + } + break; + case Long: + switch (from) { + case Double: + return emitConvert2MemoryOp(to, MOV_D2L, access); + } + break; + case Float: + switch (from) { + case Int: + return emitConvert2MemoryOp(to, MOV_I2F, access); + } + break; + case Double: + switch (from) { + case Long: + return emitConvert2MemoryOp(to, MOV_L2D, access); + } + break; + } + throw GraalInternalError.shouldNotReachHere(); + } + + static Object lock = new Object(); + + private AMD64Arithmetic getOp(ValueNode operation, Access access) { + Kind memoryKind = getMemoryKind(access); + if (operation.getClass() == IntegerAddNode.class) { + switch (memoryKind) { + case Int: + return IADD; + case Long: + return LADD; + } + } else if (operation.getClass() == FloatAddNode.class) { + switch (memoryKind) { + case Float: + return FADD; + case Double: + return DADD; + } + } else if (operation.getClass() == AndNode.class) { + switch (memoryKind) { + case Int: + return IAND; + case Long: + return LAND; + } + } else if (operation.getClass() == OrNode.class) { + switch (memoryKind) { + case Int: + return IOR; + case Long: + return LOR; + } + } else if (operation.getClass() == XorNode.class) { + switch (memoryKind) { + case Int: + return IXOR; + case Long: + return LXOR; + } + } else if (operation.getClass() == IntegerSubNode.class) { + switch (memoryKind) { + case Int: + return ISUB; + case Long: + return LSUB; + } + } else if (operation.getClass() == FloatSubNode.class) { + switch (memoryKind) { + case Float: + return FSUB; + case Double: + return DSUB; + } + } else if (operation.getClass() == IntegerMulNode.class) { + switch (memoryKind) { + case Int: + return IMUL; + case Long: + return LMUL; + } + } else if (operation.getClass() == FloatMulNode.class) { + switch (memoryKind) { + case Float: + return FMUL; + case Double: + return DMUL; + } + } + return null; + } + + @MatchRule("(If (IntegerTest=compare Read=access value))") + @MatchRule("(If (IntegerTest=compare FloatingRead=access value))") + public static class IfIntegerTest extends AMD64MatchGenerator { + IfNode root; + Access access; + ValueNode value; + + @Override + public ComplexMatchResult match(AMD64NodeLIRBuilder gen) { + return gen.emitIntegerTestBranchMemory(root, value, access); + } + } + + @MatchRule("(If (IntegerEquals=compare value Read=access))") + @MatchRule("(If (IntegerLessThan=compare value Read=access))") + @MatchRule("(If (IntegerBelowThan=compare value Read=access))") + @MatchRule("(If (IntegerEquals=compare value FloatingRead=access))") + @MatchRule("(If (IntegerLessThan=compare value FloatingRead=access))") + @MatchRule("(If (IntegerBelowThan=compare value FloatingRead=access))") + @MatchRule("(If (FloatEquals=compare value Read=access))") + @MatchRule("(If (FloatEquals=compare value FloatingRead=access))") + @MatchRule("(If (FloatLessThan=compare value Read=access))") + @MatchRule("(If (FloatLessThan=compare value FloatingRead=access))") + public static class IfCompareMemory extends AMD64MatchGenerator { + IfNode root; + Access access; + ValueNode value; + CompareNode compare; + + @Override + public ComplexMatchResult match(AMD64NodeLIRBuilder gen) { + return gen.emitCompareBranchMemory(root, compare, value, access); + } + } + + @MatchRule("(Or (LeftShift=lshift value Constant) (UnsignedRightShift=rshift value Constant))") + public static class RotateLeftConstant extends AMD64MatchGenerator { + LeftShiftNode lshift; + UnsignedRightShiftNode rshift; + + @Override + public ComplexMatchResult match(AMD64NodeLIRBuilder gen) { + if ((lshift.getShiftAmountMask() & (lshift.y().asConstant().asInt() + rshift.y().asConstant().asInt())) == 0) { + return builder -> gen.getLIRGeneratorTool().emitRol(gen.operand(lshift.x()), gen.operand(lshift.y())); + } + return null; + } + + } + + @MatchRule("(Or (LeftShift=lshift value (IntegerSub Constant=delta shiftAmount)) (UnsignedRightShift value shiftAmount))") + public static class RotateRightVariable extends AMD64MatchGenerator { + ValueNode value; + ValueNode shiftAmount; + ConstantNode delta; + + @Override + public ComplexMatchResult match(AMD64NodeLIRBuilder gen) { + if (delta.asConstant().asLong() == 0 || delta.asConstant().asLong() == 32) { + return builder -> gen.getLIRGeneratorTool().emitRor(gen.operand(value), gen.operand(shiftAmount)); + } + return null; + } + + } + + @MatchRule("(Or (LeftShift value shiftAmount) (UnsignedRightShift value (IntegerSub Constant=delta shiftAmount)))") + public static class RotateLeftVariable extends AMD64MatchGenerator { + ValueNode value; + ValueNode shiftAmount; + ConstantNode delta; + + @Override + public ComplexMatchResult match(AMD64NodeLIRBuilder gen) { + if (delta.asConstant().asLong() == 0 || delta.asConstant().asLong() == 32) { + return builder -> gen.getLIRGeneratorTool().emitRol(gen.operand(value), gen.operand(shiftAmount)); + } + return null; + } + } + + @MatchRule("(IntegerAdd value Read=access)") + @MatchRule("(IntegerSub value Read=access)") + @MatchRule("(IntegerMul value Read=access)") + @MatchRule("(FloatAdd value Read=access)") + @MatchRule("(FloatSub value Read=access)") + @MatchRule("(FloatMul value Read=access)") + @MatchRule("(Or value Read=access)") + @MatchRule("(Xor value Read=access)") + @MatchRule("(And value Read=access)") + @MatchRule("(IntegerAdd value FloatingRead=access)") + @MatchRule("(IntegerSub value FloatingRead=access)") + @MatchRule("(IntegerMul value FloatingRead=access)") + @MatchRule("(FloatAdd value FloatingRead=access)") + @MatchRule("(FloatSub value FloatingRead=access)") + @MatchRule("(FloatMul value FloatingRead=access)") + @MatchRule("(Or value FloatingRead=access)") + @MatchRule("(Xor value FloatingRead=access)") + @MatchRule("(And value FloatingRead=access)") + public static class BinaryRead extends AMD64MatchGenerator { + BinaryNode root; + Access access; + ValueNode value; + + @Override + public ComplexMatchResult match(AMD64NodeLIRBuilder gen) { + AMD64Arithmetic op = gen.getOp(root, access); + if (op != null) { + return builder -> gen.getLIRGeneratorTool().emitBinaryMemory(op, gen.getMemoryKind(access), gen.getLIRGeneratorTool().asAllocatable(gen.operand(value)), gen.makeAddress(access), + gen.getState(access)); + } + return null; + } + } + + @MatchRule("(Write Narrow=narrow value)") + public static class WriteNarrow extends AMD64MatchGenerator { + WriteNode root; + NarrowNode narrow; + + @Override + public ComplexMatchResult match(AMD64NodeLIRBuilder gen) { + return new ComplexMatchResult() { + @Override + public Value evaluate(NodeLIRBuilder builder) { + PlatformKind writeKind = gen.getLIRGeneratorTool().getPlatformKind(root.value().stamp()); + Value address = root.location().generateAddress(builder, gen.getLIRGeneratorTool(), gen.operand(root.object())); + Value v = gen.operand(narrow.getInput()); + gen.getLIRGeneratorTool().emitStore(writeKind, address, v, gen.state(root)); + return null; + } + }; + } + } + + @MatchRule("(SignExtend Read=access)") + @MatchRule("(SignExtend FloatingRead=access)") + public static class SignExtend extends AMD64MatchGenerator { + Access access; + SignExtendNode root; + + @Override + public ComplexMatchResult match(AMD64NodeLIRBuilder gen) { + return gen.emitSignExtendMemory(access, root.getInputBits(), root.getResultBits()); + } + } + + static abstract class AMD64MatchGenerator implements MatchGenerator { + public AMD64MatchGenerator() { + } + + public ComplexMatchResult match(NodeLIRBuilder gen) { + return match((AMD64NodeLIRBuilder) gen); + } + + abstract public ComplexMatchResult match(AMD64NodeLIRBuilder gen); + } + + @MatchRule("(ZeroExtend Read=access)") + @MatchRule("(ZeroExtend FloatingRead=access)") + public static class ZeroExtend extends AMD64MatchGenerator { + Access access; + ZeroExtendNode root; + + @Override + public ComplexMatchResult match(AMD64NodeLIRBuilder gen) { + Kind memoryKind = gen.getMemoryKind(access); + if (memoryKind.getBitCount() != root.getInputBits() && !memoryKind.isUnsigned()) { + /* + * The memory being read from is signed and smaller than the result size so this is + * a sign extension to inputBits followed by a zero extension to resultBits which + * can't be expressed in a memory operation. + */ + return null; + } + return new ComplexMatchResult() { + public Value evaluate(NodeLIRBuilder unused) { + return gen.getLIRGeneratorTool().emitZeroExtendMemory(memoryKind == Kind.Short ? Kind.Char : memoryKind, root.getResultBits(), gen.makeAddress(access), gen.getState(access)); + } + }; + } + } + + @MatchRule("(FloatConvert Read=access)") + @MatchRule("(FloatConvert FloatingRead=access)") + public static class FloatConvert extends AMD64MatchGenerator { + Access access; + FloatConvertNode root; + + @Override + public ComplexMatchResult match(AMD64NodeLIRBuilder gen) { + return new ComplexMatchResult() { + public Value evaluate(NodeLIRBuilder builder) { + return gen.emitFloatConvertMemory(root, access); + } + }; + } + } + + @MatchRule("(Reinterpret Read=access)") + @MatchRule("(Reinterpret FloatingRead=access)") + public static class Reinterpret extends AMD64MatchGenerator { + Access access; + ReinterpretNode root; + + @Override + public ComplexMatchResult match(AMD64NodeLIRBuilder gen) { + return new ComplexMatchResult() { + public Value evaluate(NodeLIRBuilder builder) { + PlatformKind kind = gen.getLIRGeneratorTool().getPlatformKind(root.stamp()); + return gen.emitReinterpretMemory(kind, access); + } + }; + } + } + @Override public void visitBreakpointNode(BreakpointNode node) { JavaType[] sig = new JavaType[node.arguments().size()]; @@ -103,11 +632,11 @@ @Override public void visitInfopointNode(InfopointNode i) { - append(new InfopointOp(gen.stateFor(i.getState()), i.reason)); + append(new InfopointOp(stateFor(i.getState()), i.reason)); } @Override - public AMD64LIRGenerator getLIRGenerator() { + public AMD64LIRGenerator getLIRGeneratorTool() { return (AMD64LIRGenerator) gen; } } diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.compiler.common/src/com/oracle/graal/compiler/common/FieldIntrospection.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.compiler.common/src/com/oracle/graal/compiler/common/FieldIntrospection.java Mon Apr 28 11:18:15 2014 +0200 @@ -0,0 +1,157 @@ +/* + * 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.compiler.common; + +import java.lang.reflect.*; +import java.util.*; +import java.util.concurrent.*; + +public abstract class FieldIntrospection extends UnsafeAccess { + + /** + * Interface used by {@link #rescanAllFieldOffsets(CalcOffset)} to determine the offset (in + * bytes) of a field. + */ + public interface CalcOffset { + + long getOffset(Field field); + } + + public static class DefaultCalcOffset implements CalcOffset { + + @Override + public long getOffset(Field field) { + return unsafe.objectFieldOffset(field); + } + } + + protected static final ConcurrentHashMap, FieldIntrospection> allClasses = new ConcurrentHashMap<>(); + + private final Class clazz; + protected long[] dataOffsets; + protected Map fieldNames; + protected Map> fieldTypes; + + public FieldIntrospection(Class clazz) { + this.clazz = clazz; + } + + public Class getClazz() { + return clazz; + } + + public static void rescanAllFieldOffsets(CalcOffset calc) { + for (FieldIntrospection nodeClass : allClasses.values()) { + nodeClass.rescanFieldOffsets(calc); + } + } + + protected abstract void rescanFieldOffsets(CalcOffset calc); + + public abstract static class BaseFieldScanner { + + private final CalcOffset calc; + + /** The offsets of fields that are not specially handled by subclasses. */ + public final ArrayList dataOffsets = new ArrayList<>(); + + public final Map fieldNames = new HashMap<>(); + public final Map> fieldTypes = new HashMap<>(); + + protected BaseFieldScanner(CalcOffset calc) { + this.calc = calc; + } + + public void scan(Class clazz) { + Class currentClazz = clazz; + do { + for (Field field : currentClazz.getDeclaredFields()) { + if (Modifier.isStatic(field.getModifiers())) { + continue; + } + Class type = field.getType(); + long offset = calc.getOffset(field); + + // scanField() may overwrite the name with a customized name. + fieldNames.put(offset, field.getName()); + fieldTypes.put(offset, type); + + scanField(field, type, offset); + } + currentClazz = currentClazz.getSuperclass(); + } while (currentClazz.getSuperclass() != Object.class); + } + + protected abstract void scanField(Field field, Class type, long offset); + } + + protected static void copyInto(long[] dest, long[] src) { + assert dest.length == src.length; + for (int i = 0; i < dest.length; i++) { + dest[i] = src[i]; + } + } + + protected static void copyInto(T[] dest, T[] src) { + assert dest.length == src.length; + for (int i = 0; i < dest.length; i++) { + dest[i] = src[i]; + } + } + + protected static void copyInto(T[] dest, List src) { + assert dest.length == src.size(); + for (int i = 0; i < dest.length; i++) { + dest[i] = src.get(i); + } + } + + protected static T[] arrayUsingSortedOffsets(Map map, long[] sortedOffsets, T[] result) { + for (int i = 0; i < sortedOffsets.length; i++) { + result[i] = map.get(sortedOffsets[i]); + } + return result; + } + + protected static long[] sortedLongCopy(ArrayList list1) { + Collections.sort(list1); + long[] result = new long[list1.size()]; + for (int i = 0; i < list1.size(); i++) { + result[i] = list1.get(i); + } + return result; + } + + protected static long[] sortedLongCopy(ArrayList list1, ArrayList list2) { + Collections.sort(list1); + Collections.sort(list2); + long[] result = new long[list1.size() + list2.size()]; + for (int i = 0; i < list1.size(); i++) { + result[i] = list1.get(i); + } + for (int i = 0; i < list2.size(); i++) { + result[list1.size() + i] = list2.get(i); + } + return result; + } +} diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.compiler.common/src/com/oracle/graal/compiler/common/GraalInternalError.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.compiler.common/src/com/oracle/graal/compiler/common/GraalInternalError.java Mon Apr 28 11:18:15 2014 +0200 @@ -0,0 +1,136 @@ +/* + * Copyright (c) 2011, 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.graal.compiler.common; + +import java.util.*; + +/** + * This error represents a conditions that should never occur during normal operation. + */ +public class GraalInternalError extends Error { + + private static final long serialVersionUID = 531632331813456233L; + private final ArrayList context = new ArrayList<>(); + + public static RuntimeException unimplemented() { + throw new GraalInternalError("unimplemented"); + } + + public static RuntimeException unimplemented(String msg) { + throw new GraalInternalError("unimplemented: %s", msg); + } + + public static RuntimeException shouldNotReachHere() { + throw new GraalInternalError("should not reach here"); + } + + public static RuntimeException shouldNotReachHere(String msg) { + throw new GraalInternalError("should not reach here: %s", msg); + } + + /** + * Checks a given condition and throws a {@link GraalInternalError} if it is false. Guarantees + * are stronger than assertions in that they are always checked. Error messages for guarantee + * violations should clearly indicate the nature of the problem as well as a suggested solution + * if possible. + * + * @param condition the condition to check + * @param msg the message that will be associated with the error, in + * {@link String#format(String, Object...)} syntax + * @param args arguments to the format string + */ + public static void guarantee(boolean condition, String msg, Object... args) { + if (!condition) { + throw new GraalInternalError("failed guarantee: " + msg, args); + } + } + + /** + * This constructor creates a {@link GraalInternalError} with a message assembled via + * {@link String#format(String, Object...)}. It always uses the ENGLISH locale in order to + * always generate the same output. + * + * @param msg the message that will be associated with the error, in String.format syntax + * @param args parameters to String.format - parameters that implement {@link Iterable} will be + * expanded into a [x, x, ...] representation. + */ + public GraalInternalError(String msg, Object... args) { + super(format(msg, args)); + } + + /** + * This constructor creates a {@link GraalInternalError} for a given causing Throwable instance. + * + * @param cause the original exception that contains additional information on this error + */ + public GraalInternalError(Throwable cause) { + super(cause); + } + + /** + * This constructor creates a {@link GraalInternalError} from a given GraalInternalError + * instance. + * + * @param e the original GraalInternalError + */ + public GraalInternalError(GraalInternalError e) { + super(e); + context.addAll(e.context); + } + + @Override + public String toString() { + StringBuilder str = new StringBuilder(); + str.append(super.toString()); + for (String s : context) { + str.append("\n\tat ").append(s); + } + return str.toString(); + } + + private static String format(String msg, Object... args) { + if (args != null) { + // expand Iterable parameters into a list representation + for (int i = 0; i < args.length; i++) { + if (args[i] instanceof Iterable) { + ArrayList list = new ArrayList<>(); + for (Object o : (Iterable) args[i]) { + list.add(o); + } + args[i] = list.toString(); + } + } + } + return String.format(Locale.ENGLISH, msg, args); + } + + public GraalInternalError addContext(String newContext) { + this.context.add(newContext); + return this; + } + + public GraalInternalError addContext(String name, Object obj) { + return addContext(format("%s: %s", name, obj)); + } + +} diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.compiler.common/src/com/oracle/graal/compiler/common/GraalOptions.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.compiler.common/src/com/oracle/graal/compiler/common/GraalOptions.java Mon Apr 28 11:18:15 2014 +0200 @@ -0,0 +1,287 @@ +/* + * Copyright (c) 2009, 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.graal.compiler.common; + +import com.oracle.graal.options.*; + +/** + * This class encapsulates options that control the behavior of the Graal compiler. + */ +// @formatter:off +public final class GraalOptions { + + @Option(help = "Use baseline compiler configuration") + public static final OptionValue UseBaselineCompiler = new OptionValue<>(false); + @Option(help = "Enable use of compiler intrinsics") + public static final OptionValue Intrinsify = new OptionValue<>(true); + @Option(help = "Enable inlining of monomorphic calls") + public static final OptionValue InlineMonomorphicCalls = new OptionValue<>(true); + @Option(help = "Enable inlining of polymorphic calls") + public static final OptionValue InlinePolymorphicCalls = new OptionValue<>(true); + @Option(help = "Enable inlining of megamorphic calls") + public static final OptionValue InlineMegamorphicCalls = new OptionValue<>(true); + @Option(help = "") + public static final OptionValue MegamorphicInliningMinMethodProbability = new OptionValue<>(0.33D); + @Option(help = "") + public static final OptionValue MaximumDesiredSize = new OptionValue<>(20000); + @Option(help = "") + public static final OptionValue MaximumRecursiveInlining = new OptionValue<>(5); + + // inlining settings + @Option(help = "") + public static final OptionValue BoostInliningForEscapeAnalysis = new OptionValue<>(2f); + @Option(help = "") + public static final OptionValue RelevanceCapForInlining = new OptionValue<>(1f); + @Option(help = "") + public static final OptionValue CapInheritedRelevance = new OptionValue<>(1f); + @Option(help = "") + public static final OptionValue IterativeInlining = new OptionValue<>(false); + + @Option(help = "") + public static final OptionValue TrivialInliningSize = new OptionValue<>(10); + @Option(help = "") + public static final OptionValue MaximumInliningSize = new OptionValue<>(300); + @Option(help = "") + public static final OptionValue SmallCompiledLowLevelGraphSize = new OptionValue<>(300); + @Option(help = "") + public static final OptionValue LimitInlinedInvokes = new OptionValue<>(5.0); + @Option(help = "") + public static final OptionValue InlineEverything = new OptionValue<>(false); + + // escape analysis settings + @Option(help = "") + public static final OptionValue PartialEscapeAnalysis = new OptionValue<>(true); + @Option(help = "") + public static final OptionValue EscapeAnalysisIterations = new OptionValue<>(2); + @Option(help = "") + public static final OptionValue EscapeAnalyzeOnly = new OptionValue<>(null); + @Option(help = "") + public static final OptionValue MaximumEscapeAnalysisArrayLength = new OptionValue<>(32); + @Option(help = "") + public static final OptionValue PEAInliningHints = new OptionValue<>(false); + + @Option(help = "") + public static final OptionValue TailDuplicationProbability = new OptionValue<>(0.5); + @Option(help = "") + public static final OptionValue TailDuplicationTrivialSize = new OptionValue<>(1); + + // profiling information + @Option(help = "") + public static final OptionValue DeoptsToDisableOptimisticOptimization = new OptionValue<>(40); + + // graph caching + @Option(help = "") + public static final OptionValue CacheGraphs = new OptionValue<>(true); + + //loop transform settings TODO (gd) tune + @Option(help = "") + public static final OptionValue LoopPeeling = new OptionValue<>(true); + @Option(help = "") + public static final OptionValue ReassociateInvariants = new OptionValue<>(true); + @Option(help = "") + public static final OptionValue FullUnroll = new OptionValue<>(true); + @Option(help = "") + public static final OptionValue LoopUnswitch = new OptionValue<>(true); + @Option(help = "") + public static final OptionValue FullUnrollMaxNodes = new OptionValue<>(300); + @Option(help = "") + public static final OptionValue ExactFullUnrollMaxNodes = new OptionValue<>(1200); + @Option(help = "") + public static final OptionValue MinimumPeelProbability = new OptionValue<>(0.35f); + @Option(help = "") + public static final OptionValue LoopMaxUnswitch = new OptionValue<>(3); + @Option(help = "") + public static final OptionValue LoopUnswitchMaxIncrease = new OptionValue<>(50); + @Option(help = "") + public static final OptionValue LoopUnswitchUncertaintyBoost = new OptionValue<>(5); + @Option(help = "") + public static final OptionValue UseLoopLimitChecks = new OptionValue<>(true); + + // debugging settings + @Option(help = "") + public static final OptionValue ZapStackOnMethodEntry = new OptionValue<>(false); + @Option(help = "") + public static final OptionValue DeoptALot = new OptionValue<>(false); + @Option(help = "") + public static final OptionValue VerifyPhases = new OptionValue<>(false); + + @Option(help = "") + public static final OptionValue PrintFilter = new OptionValue<>(null); + + // Debug settings: + @Option(help = "") + public static final OptionValue BootstrapReplacements = new OptionValue<>(false); + @Option(help = "") + public static final OptionValue GCDebugStartCycle = new OptionValue<>(-1); + // Ideal graph visualizer output settings + @Option(help = "Dump IdealGraphVisualizer output in binary format") + public static final OptionValue PrintBinaryGraphs = new OptionValue<>(true); + @Option(help = "Output probabilities for fixed nodes during binary graph dumping") + public static final OptionValue PrintGraphProbabilities = new OptionValue<>(false); + @Option(help = "Enable dumping to the C1Visualizer. Enabling this option implies PrintBackendCFG.") + public static final OptionValue PrintCFG = new OptionValue<>(false); + @Option(help = "Enable dumping LIR, register allocation and code generation info to the C1Visualizer.") + public static final OptionValue PrintBackendCFG = new OptionValue<>(true); + @Option(help = "") + public static final OptionValue PrintIdealGraphFile = new OptionValue<>(false); + @Option(help = "") + public static final OptionValue PrintIdealGraphAddress = new OptionValue<>("127.0.0.1"); + @Option(help = "") + public static final OptionValue PrintIdealGraphPort = new OptionValue<>(4444); + @Option(help = "") + public static final OptionValue PrintBinaryGraphPort = new OptionValue<>(4445); + + // Other printing settings + @Option(help = "") + public static final OptionValue PrintCompilation = new OptionValue<>(false); + @Option(help = "") + public static final OptionValue PrintAfterCompilation = new OptionValue<>(false); + @Option(help = "Print profiling information when parsing a method's bytecode") + public static final OptionValue PrintProfilingInformation = new OptionValue<>(false); + @Option(help = "") + public static final OptionValue PrintCodeBytes = new OptionValue<>(false); + @Option(help = "") + public static final OptionValue PrintBailout = new OptionValue<>(false); + @Option(help = "") + public static final OptionValue TraceEscapeAnalysis = new OptionValue<>(false); + @Option(help = "") + public static final OptionValue ExitVMOnBailout = new OptionValue<>(false); + @Option(help = "") + public static final OptionValue ExitVMOnException = new OptionValue<>(true); + @Option(help = "") + public static final OptionValue PrintStackTraceOnException = new OptionValue<>(false); + @Option(help = "Set a phase after which the decompiler dumps the graph, -G:Dump= required") + public static final OptionValue DecompileAfterPhase = new OptionValue<>(null); + + // HotSpot command line options + @Option(help = "") + public static final OptionValue HotSpotPrintCompilation = new OptionValue<>(false); + @Option(help = "") + public static final OptionValue HotSpotCIPrintCompilerName = new OptionValue<>(false); + @Option(help = "") + public static final OptionValue HotSpotPrintInlining = new OptionValue<>(false); + + // Register allocator debugging + @Option(help = "") + public static final OptionValue RegisterPressure = new OptionValue<>(null); + + // Code generator settings + @Option(help = "") + public static final OptionValue FlowSensitiveReduction = new OptionValue<>(false); + @Option(help = "") + public static final OptionValue ConditionalElimination = new OptionValue<>(true); + @Option(help = "") + public static final OptionValue UseProfilingInformation = new OptionValue<>(true); + @Option(help = "") + public static final OptionValue RemoveNeverExecutedCode = new OptionValue<>(true); + @Option(help = "") + public static final OptionValue UseExceptionProbability = new OptionValue<>(true); + @Option(help = "") + public static final OptionValue UseExceptionProbabilityForOperations = new OptionValue<>(true); + @Option(help = "") + public static final OptionValue OmitHotExceptionStacktrace = new OptionValue<>(false); + @Option(help = "") + public static final OptionValue GenSafepoints = new OptionValue<>(true); + @Option(help = "") + public static final OptionValue GenLoopSafepoints = new OptionValue<>(true); + @Option(help = "") + public static final OptionValue UseTypeCheckHints = new OptionValue<>(true); + @Option(help = "") + public static final OptionValue InlineVTableStubs = new OptionValue<>(true); + @Option(help = "") + public static final OptionValue AlwaysInlineVTableStubs = new OptionValue<>(false); + @Option(help = "") + public static final OptionValue GenAssertionCode = new OptionValue<>(false); + @Option(help = "") + public static final OptionValue AlignCallsForPatching = new OptionValue<>(true); + @Option(help = "") + public static final OptionValue ResolveClassBeforeStaticInvoke = new OptionValue<>(false); + @Option(help = "") + public static final OptionValue CanOmitFrame = new OptionValue<>(true); + + @Option(help = "") + public static final OptionValue MemoryAwareScheduling = new OptionValue<>(true); + + // Translating tableswitch instructions + @Option(help = "") + public static final OptionValue MinimumJumpTableSize = new OptionValue<>(5); + @Option(help = "") + public static final OptionValue RangeTestsSwitchDensity = new OptionValue<>(5); + @Option(help = "") + public static final OptionValue MinTableSwitchDensity = new OptionValue<>(0.5); + + // Ahead of time compilation + @Option(help = "Try to avoid emitting code where patching is required") + public static final OptionValue ImmutableCode = new OptionValue<>(false); + + @Option(help = "") + public static final OptionValue CallArrayCopy = new OptionValue<>(true); + + // Runtime settings + @Option(help = "") + public static final OptionValue SupportJsrBytecodes = new OptionValue<>(true); + + @Option(help = "") + public static final OptionValue OptAssumptions = new OptionValue<>(true); + @Option(help = "") + public static final OptionValue OptConvertDeoptsToGuards = new OptionValue<>(true); + @Option(help = "") + public static final OptionValue OptReadElimination = new OptionValue<>(true); + @Option(help = "") + public static final OptionValue OptCanonicalizer = new OptionValue<>(true); + @Option(help = "") + public static final OptionValue OptDeoptimizationGrouping = new OptionValue<>(true); + @Option(help = "") + public static final OptionValue OptScheduleOutOfLoops = new OptionValue<>(true); + @Option(help = "") + public static final OptionValue OptEliminateGuards = new OptionValue<>(true); + @Option(help = "") + public static final OptionValue OptImplicitNullChecks = new OptionValue<>(true); + @Option(help = "") + public static final OptionValue OptLivenessAnalysis = new OptionValue<>(true); + @Option(help = "") + public static final OptionValue OptLoopTransform = new OptionValue<>(true); + @Option(help = "") + public static final OptionValue OptFloatingReads = new OptionValue<>(true); + @Option(help = "") + public static final OptionValue OptTailDuplication = new OptionValue<>(true); + @Option(help = "") + public static final OptionValue OptEliminatePartiallyRedundantGuards = new OptionValue<>(true); + @Option(help = "") + public static final OptionValue OptFilterProfiledTypes = new OptionValue<>(true); + @Option(help = "") + public static final OptionValue OptDevirtualizeInvokesOptimistically = new OptionValue<>(true); + @Option(help = "") + public static final OptionValue OptPushThroughPi = new OptionValue<>(true); + @Option(help = "Allow backend to emit arithmetic and compares directly against memory.") + public static final OptionValue OptFoldMemory = new OptionValue<>(false); + @Option(help = "Allow backend to match complex expressions.") + public static final OptionValue MatchExpressions = new OptionValue<>(true); + + + /** + * Counts the various paths taken through snippets. + */ + @Option(help = "") + public static final OptionValue SnippetCounters = new OptionValue<>(false); +} diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.compiler.common/src/com/oracle/graal/compiler/common/UnsafeAccess.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.compiler.common/src/com/oracle/graal/compiler/common/UnsafeAccess.java Mon Apr 28 11:18:15 2014 +0200 @@ -0,0 +1,102 @@ +/* + * 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.compiler.common; + +import java.lang.reflect.*; + +import sun.misc.*; + +public class UnsafeAccess { + + /** + * An instance of {@link Unsafe} for use within Graal. + */ + public static final Unsafe unsafe = getUnsafe(); + + private static Unsafe getUnsafe() { + try { + // this will fail if Graal is not part of the boot class path + return Unsafe.getUnsafe(); + } catch (SecurityException e) { + // nothing to do + } + try { + Field theUnsafeInstance = Unsafe.class.getDeclaredField("theUnsafe"); + theUnsafeInstance.setAccessible(true); + return (Unsafe) theUnsafeInstance.get(Unsafe.class); + } catch (Exception e) { + // currently we rely on being able to use Unsafe... + throw new RuntimeException("exception while trying to get Unsafe.theUnsafe via reflection:", e); + } + } + + /** + * Copies the contents of a {@link String} to a native memory buffer as a {@code '\0'} + * terminated C string. The native memory buffer is allocated via + * {@link Unsafe#allocateMemory(long)}. The caller is responsible for releasing the buffer when + * it is no longer needed via {@link Unsafe#freeMemory(long)}. + * + * @return the native memory pointer of the C string created from {@code s} + */ + public static long createCString(String s) { + return writeCString(s, unsafe.allocateMemory(s.length() + 1)); + } + + /** + * Reads a {@code '\0'} terminated C string from native memory and converts it to a + * {@link String}. + * + * @return a Java string + */ + public static String readCString(long address) { + if (address == 0) { + return null; + } + StringBuffer sb = new StringBuffer(); + for (int i = 0;; i++) { + char c = (char) unsafe.getByte(address + i); + if (c == 0) { + break; + } + sb.append(c); + } + return sb.toString(); + } + + /** + * Writes the contents of a {@link String} to a native memory buffer as a {@code '\0'} + * terminated C string. The caller is responsible for ensuring the buffer is at least + * {@code s.length() + 1} bytes long. The caller is also responsible for releasing the buffer + * when it is no longer. + * + * @return the value of {@code buf} + */ + public static long writeCString(String s, long buf) { + int size = s.length(); + for (int i = 0; i < size; i++) { + unsafe.putByte(buf + i, (byte) s.charAt(i)); + } + unsafe.putByte(buf + size, (byte) '\0'); + return buf; + } +} diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.compiler.common/src/com/oracle/graal/compiler/common/calc/Condition.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.compiler.common/src/com/oracle/graal/compiler/common/calc/Condition.java Mon Apr 28 11:18:15 2014 +0200 @@ -0,0 +1,634 @@ +/* + * Copyright (c) 2009, 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.graal.compiler.common.calc; + +import com.oracle.graal.api.code.*; +import com.oracle.graal.api.meta.*; +import com.oracle.graal.compiler.common.*; + +/** + * Condition codes used in conditionals. + */ +public enum Condition { + /** + * Equal. + */ + EQ("=="), + + /** + * Not equal. + */ + NE("!="), + + /** + * Signed less than. + */ + LT("<"), + + /** + * Signed less than or equal. + */ + LE("<="), + + /** + * Signed greater than. + */ + GT(">"), + + /** + * Signed greater than or equal. + */ + GE(">="), + + /** + * Unsigned greater than or equal ("above than or equal"). + */ + AE("|>=|"), + + /** + * Unsigned less than or equal ("below than or equal"). + */ + BE("|<=|"), + + /** + * Unsigned greater than ("above than"). + */ + AT("|>|"), + + /** + * Unsigned less than ("below than"). + */ + BT("|<|"); + + public final String operator; + + private Condition(String operator) { + this.operator = operator; + } + + public boolean check(int left, int right) { + switch (this) { + case EQ: + return left == right; + case NE: + return left != right; + case LT: + return left < right; + case LE: + return left <= right; + case GT: + return left > right; + case GE: + return left >= right; + case AE: + return UnsignedMath.aboveOrEqual(left, right); + case BE: + return UnsignedMath.belowOrEqual(left, right); + case AT: + return UnsignedMath.aboveThan(left, right); + case BT: + return UnsignedMath.belowThan(left, right); + } + throw new IllegalArgumentException(this.toString()); + } + + /** + * Given a condition and its negation, this method returns true for one of the two and false for + * the other one. This can be used to keep comparisons in a canonical form. + * + * @return true if this condition is considered to be the canonical form, false otherwise. + */ + public boolean isCanonical() { + switch (this) { + case EQ: + return true; + case NE: + return false; + case LT: + return true; + case LE: + return false; + case GT: + return false; + case GE: + return false; + case BT: + return true; + case BE: + return false; + case AT: + return false; + case AE: + return false; + } + throw new IllegalArgumentException(this.toString()); + } + + /** + * Returns true if the condition needs to be mirrored to get to a canonical condition. The + * result of the mirroring operation might still need to be negated to achieve a canonical form. + */ + public boolean canonicalMirror() { + switch (this) { + case EQ: + return false; + case NE: + return false; + case LT: + return false; + case LE: + return true; + case GT: + return true; + case GE: + return false; + case BT: + return false; + case BE: + return true; + case AT: + return true; + case AE: + return false; + } + throw new IllegalArgumentException(this.toString()); + } + + /** + * Returns true if the condition needs to be negated to get to a canonical condition. The result + * of the negation might still need to be mirrored to achieve a canonical form. + */ + public boolean canonicalNegate() { + switch (this) { + case EQ: + return false; + case NE: + return true; + case LT: + return false; + case LE: + return true; + case GT: + return false; + case GE: + return true; + case BT: + return false; + case BE: + return true; + case AT: + return false; + case AE: + return true; + } + throw new IllegalArgumentException(this.toString()); + } + + /** + * Negate this conditional. + * + * @return the condition that represents the negation + */ + public final Condition negate() { + switch (this) { + case EQ: + return NE; + case NE: + return EQ; + case LT: + return GE; + case LE: + return GT; + case GT: + return LE; + case GE: + return LT; + case BT: + return AE; + case BE: + return AT; + case AT: + return BE; + case AE: + return BT; + } + throw new IllegalArgumentException(this.toString()); + } + + public boolean implies(Condition other) { + if (other == this) { + return true; + } + switch (this) { + case EQ: + return other == LE || other == GE || other == BE || other == AE; + case NE: + return false; + case LT: + return other == LE || other == NE; + case LE: + return false; + case GT: + return other == GE || other == NE; + case GE: + return false; + case BT: + return other == BE || other == NE; + case BE: + return false; + case AT: + return other == AE || other == NE; + case AE: + return false; + } + throw new IllegalArgumentException(this.toString()); + } + + /** + * Mirror this conditional (i.e. commute "a op b" to "b op' a") + * + * @return the condition representing the equivalent commuted operation + */ + public final Condition mirror() { + switch (this) { + case EQ: + return EQ; + case NE: + return NE; + case LT: + return GT; + case LE: + return GE; + case GT: + return LT; + case GE: + return LE; + case BT: + return AT; + case BE: + return AE; + case AT: + return BT; + case AE: + return BE; + } + throw new IllegalArgumentException(); + } + + /** + * Returns true if this condition represents an unsigned comparison. EQ and NE are not + * considered to be unsigned. + */ + public final boolean isUnsigned() { + return this == Condition.BT || this == Condition.BE || this == Condition.AT || this == Condition.AE; + } + + /** + * Checks if this conditional operation is commutative. + * + * @return {@code true} if this operation is commutative + */ + public final boolean isCommutative() { + return this == EQ || this == NE; + } + + /** + * Attempts to fold a comparison between two constants and return the result. + * + * @param lt the constant on the left side of the comparison + * @param rt the constant on the right side of the comparison + * @param constantReflection needed to compare constants + * @return {@link Boolean#TRUE} if the comparison is known to be true, {@link Boolean#FALSE} if + * the comparison is known to be false + */ + public boolean foldCondition(Constant lt, Constant rt, ConstantReflectionProvider constantReflection) { + assert !lt.getKind().isNumericFloat() && !rt.getKind().isNumericFloat(); + return foldCondition(lt, rt, constantReflection, false); + } + + /** + * Attempts to fold a comparison between two constants and return the result. + * + * @param lt the constant on the left side of the comparison + * @param rt the constant on the right side of the comparison + * @param constantReflection needed to compare constants + * @param unorderedIsTrue true if an undecided float comparison should result in "true" + * @return true if the comparison is known to be true, false if the comparison is known to be + * false + */ + public boolean foldCondition(Constant lt, Constant rt, ConstantReflectionProvider constantReflection, boolean unorderedIsTrue) { + switch (lt.getKind()) { + case Boolean: + case Byte: + case Char: + case Short: + case Int: { + int x = lt.asInt(); + int y = rt.asInt(); + switch (this) { + case EQ: + return x == y; + case NE: + return x != y; + case LT: + return x < y; + case LE: + return x <= y; + case GT: + return x > y; + case GE: + return x >= y; + case AE: + return UnsignedMath.aboveOrEqual(x, y); + case BE: + return UnsignedMath.belowOrEqual(x, y); + case AT: + return UnsignedMath.aboveThan(x, y); + case BT: + return UnsignedMath.belowThan(x, y); + default: + throw new GraalInternalError("expected condition: %s", this); + } + } + case Long: { + long x = lt.asLong(); + long y = rt.asLong(); + switch (this) { + case EQ: + return x == y; + case NE: + return x != y; + case LT: + return x < y; + case LE: + return x <= y; + case GT: + return x > y; + case GE: + return x >= y; + case AE: + return UnsignedMath.aboveOrEqual(x, y); + case BE: + return UnsignedMath.belowOrEqual(x, y); + case AT: + return UnsignedMath.aboveThan(x, y); + case BT: + return UnsignedMath.belowThan(x, y); + default: + throw new GraalInternalError("expected condition: %s", this); + } + } + case Object: { + Boolean equal = constantReflection.constantEquals(lt, rt); + if (equal != null) { + switch (this) { + case EQ: + return equal.booleanValue(); + case NE: + return !equal.booleanValue(); + default: + throw new GraalInternalError("expected condition: %s", this); + } + } + } + case Float: { + float x = lt.asFloat(); + float y = rt.asFloat(); + if (Float.isNaN(x) || Float.isNaN(y)) { + return unorderedIsTrue; + } + switch (this) { + case EQ: + return x == y; + case NE: + return x != y; + case LT: + return x < y; + case LE: + return x <= y; + case GT: + return x > y; + case GE: + return x >= y; + default: + throw new GraalInternalError("expected condition: %s", this); + } + } + case Double: { + double x = lt.asDouble(); + double y = rt.asDouble(); + if (Double.isNaN(x) || Double.isNaN(y)) { + return unorderedIsTrue; + } + switch (this) { + case EQ: + return x == y; + case NE: + return x != y; + case LT: + return x < y; + case LE: + return x <= y; + case GT: + return x > y; + case GE: + return x >= y; + default: + throw new GraalInternalError("expected condition: %s", this); + } + } + default: + throw new GraalInternalError("expected value kind %s while folding condition: %s", lt.getKind(), this); + } + } + + public Condition join(Condition other) { + if (other == this) { + return this; + } + switch (this) { + case EQ: + if (other == LE || other == GE || other == BE || other == AE) { + return EQ; + } else { + return null; + } + case NE: + if (other == LT || other == GT || other == BT || other == AT) { + return other; + } else if (other == LE) { + return LT; + } else if (other == GE) { + return GT; + } else if (other == BE) { + return BT; + } else if (other == AE) { + return AT; + } else { + return null; + } + case LE: + if (other == GE || other == EQ) { + return EQ; + } else if (other == NE || other == LT) { + return LT; + } else { + return null; + } + case LT: + if (other == NE || other == LE) { + return LT; + } else { + return null; + } + case GE: + if (other == LE || other == EQ) { + return EQ; + } else if (other == NE || other == GT) { + return GT; + } else { + return null; + } + case GT: + if (other == NE || other == GE) { + return GT; + } else { + return null; + } + case BE: + if (other == AE || other == EQ) { + return EQ; + } else if (other == NE || other == BT) { + return BT; + } else { + return null; + } + case BT: + if (other == NE || other == BE) { + return BT; + } else { + return null; + } + case AE: + if (other == BE || other == EQ) { + return EQ; + } else if (other == NE || other == AT) { + return AT; + } else { + return null; + } + case AT: + if (other == NE || other == AE) { + return AT; + } else { + return null; + } + } + throw new IllegalArgumentException(this.toString()); + } + + public Condition meet(Condition other) { + if (other == this) { + return this; + } + switch (this) { + case EQ: + if (other == LE || other == GE || other == BE || other == AE) { + return other; + } else if (other == LT) { + return LE; + } else if (other == GT) { + return GE; + } else if (other == BT) { + return BE; + } else if (other == AT) { + return AE; + } else { + return null; + } + case NE: + if (other == LT || other == GT || other == BT || other == AT) { + return NE; + } else { + return null; + } + case LE: + if (other == EQ || other == LT) { + return LE; + } else { + return null; + } + case LT: + if (other == EQ || other == LE) { + return LE; + } else if (other == NE || other == GT) { + return NE; + } else { + return null; + } + case GE: + if (other == EQ || other == GT) { + return GE; + } else { + return null; + } + case GT: + if (other == EQ || other == GE) { + return GE; + } else if (other == NE || other == LT) { + return NE; + } else { + return null; + } + case BE: + if (other == EQ || other == BT) { + return BE; + } else { + return null; + } + case BT: + if (other == EQ || other == BE) { + return BE; + } else if (other == NE || other == AT) { + return NE; + } else { + return null; + } + case AE: + if (other == EQ || other == AT) { + return AE; + } else { + return null; + } + case AT: + if (other == EQ || other == AE) { + return AE; + } else if (other == NE || other == BT) { + return NE; + } else { + return null; + } + } + throw new IllegalArgumentException(this.toString()); + } +} diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.compiler.common/src/com/oracle/graal/compiler/common/calc/FloatConvert.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.compiler.common/src/com/oracle/graal/compiler/common/calc/FloatConvert.java Mon Apr 28 11:18:15 2014 +0200 @@ -0,0 +1,65 @@ +/* + * Copyright (c) 2014, 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.graal.compiler.common.calc; + +import com.oracle.graal.compiler.common.*; + +public enum FloatConvert { + F2I, + D2I, + F2L, + D2L, + I2F, + L2F, + D2F, + I2D, + L2D, + F2D; + + public FloatConvert reverse() { + switch (this) { + case D2F: + return F2D; + case D2I: + return I2D; + case D2L: + return L2D; + case F2D: + return D2F; + case F2I: + return I2F; + case F2L: + return L2F; + case I2D: + return D2I; + case I2F: + return F2I; + case L2D: + return D2L; + case L2F: + return F2L; + default: + throw GraalInternalError.shouldNotReachHere(); + } + } +} \ No newline at end of file diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.compiler.common/src/com/oracle/graal/compiler/common/cfg/AbstractBlock.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.compiler.common/src/com/oracle/graal/compiler/common/cfg/AbstractBlock.java Mon Apr 28 11:18:15 2014 +0200 @@ -0,0 +1,58 @@ +/* + * Copyright (c) 2014, 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.graal.compiler.common.cfg; + +import java.util.*; + +public interface AbstractBlock> { + + int getId(); + + Loop getLoop(); + + int getLoopDepth(); + + boolean isLoopHeader(); + + boolean isLoopEnd(); + + boolean isExceptionEntry(); + + List getPredecessors(); + + int getPredecessorCount(); + + List getSuccessors(); + + int getSuccessorCount(); + + int getLinearScanNumber(); + + void setLinearScanNumber(int linearScanNumber); + + boolean isAligned(); + + void setAlign(boolean align); + + T getDominator(); +} diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.compiler.common/src/com/oracle/graal/compiler/common/cfg/AbstractBlockBase.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.compiler.common/src/com/oracle/graal/compiler/common/cfg/AbstractBlockBase.java Mon Apr 28 11:18:15 2014 +0200 @@ -0,0 +1,104 @@ +/* + * Copyright (c) 2009, 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.common.cfg; + +import java.util.*; + +public abstract class AbstractBlockBase> implements AbstractBlock { + + protected int id; + + protected List predecessors; + protected List successors; + + private T dominator; + + private boolean align; + private int linearScanNumber; + + protected AbstractBlockBase() { + this.id = AbstractControlFlowGraph.BLOCK_ID_INITIAL; + this.linearScanNumber = -1; + } + + public int getId() { + return id; + } + + public void setId(int id) { + this.id = id; + } + + public List getPredecessors() { + return predecessors; + } + + public void setPredecessors(List predecessors) { + this.predecessors = predecessors; + } + + public List getSuccessors() { + return successors; + } + + public void setSuccessors(List successors) { + this.successors = successors; + } + + public T getDominator() { + return dominator; + } + + public void setDominator(T dominator) { + this.dominator = dominator; + } + + @Override + public String toString() { + return "B" + id; + } + + public int getPredecessorCount() { + return getPredecessors().size(); + } + + public int getSuccessorCount() { + return getSuccessors().size(); + } + + public int getLinearScanNumber() { + return linearScanNumber; + } + + public void setLinearScanNumber(int linearScanNumber) { + this.linearScanNumber = linearScanNumber; + } + + public boolean isAligned() { + return align; + } + + public void setAlign(boolean align) { + this.align = align; + } +} diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.compiler.common/src/com/oracle/graal/compiler/common/cfg/AbstractControlFlowGraph.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.compiler.common/src/com/oracle/graal/compiler/common/cfg/AbstractControlFlowGraph.java Mon Apr 28 11:18:15 2014 +0200 @@ -0,0 +1,37 @@ +/* + * Copyright (c) 2014, 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.graal.compiler.common.cfg; + +import java.util.*; + +public interface AbstractControlFlowGraph> { + + static final int BLOCK_ID_INITIAL = -1; + static final int BLOCK_ID_VISITED = -2; + + T[] getBlocks(); + + Collection> getLoops(); + + T getStartBlock(); +} diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.compiler.common/src/com/oracle/graal/compiler/common/cfg/BlockMap.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.compiler.common/src/com/oracle/graal/compiler/common/cfg/BlockMap.java Mon Apr 28 11:18:15 2014 +0200 @@ -0,0 +1,41 @@ +/* + * 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.compiler.common.cfg; + +public class BlockMap { + + private final T[] data; + + @SuppressWarnings("unchecked") + public BlockMap(AbstractControlFlowGraph cfg) { + data = (T[]) new Object[cfg.getBlocks().length]; + } + + public T get(AbstractBlock block) { + return data[block.getId()]; + } + + public void put(AbstractBlock block, T value) { + data[block.getId()] = value; + } +} diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.compiler.common/src/com/oracle/graal/compiler/common/cfg/Loop.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.compiler.common/src/com/oracle/graal/compiler/common/cfg/Loop.java Mon Apr 28 11:18:15 2014 +0200 @@ -0,0 +1,60 @@ +/* + * 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.compiler.common.cfg; + +import java.util.*; + +public abstract class Loop> { + + public final Loop parent; + public final List> children; + + public final int depth; + public final int index; + public final T header; + public final List blocks; + public final List exits; + + protected Loop(Loop parent, int index, T header) { + this.parent = parent; + if (parent != null) { + this.depth = parent.depth + 1; + parent.children.add(this); + } else { + this.depth = 1; + } + this.index = index; + this.header = header; + this.blocks = new ArrayList<>(); + this.children = new ArrayList<>(); + this.exits = new ArrayList<>(); + } + + public abstract long numBackedges(); + + @Override + public String toString() { + return "loop " + index + " depth " + depth + (parent != null ? " outer " + parent.index : ""); + } +} diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.compiler.common/src/com/oracle/graal/compiler/common/spi/CodeGenProviders.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.compiler.common/src/com/oracle/graal/compiler/common/spi/CodeGenProviders.java Mon Apr 28 11:18:15 2014 +0200 @@ -0,0 +1,42 @@ +/* + * Copyright (c) 2013, 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.graal.compiler.common.spi; + +import com.oracle.graal.api.code.*; +import com.oracle.graal.api.meta.*; + +/** + * A set of providers which are required for LIR and/or code generation. Some may not be present + * (i.e., null). + */ +public interface CodeGenProviders { + + MetaAccessProvider getMetaAccess(); + + CodeCacheProvider getCodeCache(); + + ForeignCallsProvider getForeignCalls(); + + ConstantReflectionProvider getConstantReflection(); + +} diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.compiler.common/src/com/oracle/graal/compiler/common/spi/PlatformKindTool.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.compiler.common/src/com/oracle/graal/compiler/common/spi/PlatformKindTool.java Mon Apr 28 11:18:15 2014 +0200 @@ -0,0 +1,37 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.graal.compiler.common.spi; + +import com.oracle.graal.api.meta.*; + +/** + * This interface can be used to access platform and VM specific kinds. + */ +public interface PlatformKindTool { + + PlatformKind getIntegerKind(int bits); + + PlatformKind getFloatingKind(int bits); + + PlatformKind getObjectKind(); +} diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.compiler.common/src/com/oracle/graal/compiler/common/type/FloatStamp.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.compiler.common/src/com/oracle/graal/compiler/common/type/FloatStamp.java Mon Apr 28 11:18:15 2014 +0200 @@ -0,0 +1,234 @@ +/* + * Copyright (c) 2012, 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.graal.compiler.common.type; + +import com.oracle.graal.api.meta.*; +import com.oracle.graal.compiler.common.*; +import com.oracle.graal.compiler.common.spi.*; + +public class FloatStamp extends PrimitiveStamp { + + private final double lowerBound; + private final double upperBound; + private final boolean nonNaN; + + protected FloatStamp(int bits) { + this(bits, Double.NEGATIVE_INFINITY, Double.POSITIVE_INFINITY, false); + } + + public FloatStamp(int bits, double lowerBound, double upperBound, boolean nonNaN) { + super(bits); + this.lowerBound = lowerBound; + this.upperBound = upperBound; + this.nonNaN = nonNaN; + } + + @Override + public Stamp unrestricted() { + return new FloatStamp(getBits()); + } + + @Override + public Stamp illegal() { + return new FloatStamp(getBits(), Double.POSITIVE_INFINITY, Double.NEGATIVE_INFINITY, true); + } + + @Override + public boolean isLegal() { + return lowerBound <= upperBound || !nonNaN; + } + + @Override + public Kind getStackKind() { + if (getBits() > 32) { + return Kind.Double; + } else { + return Kind.Float; + } + } + + @Override + public PlatformKind getPlatformKind(PlatformKindTool tool) { + return tool.getFloatingKind(getBits()); + } + + @Override + public ResolvedJavaType javaType(MetaAccessProvider metaAccess) { + switch (getBits()) { + case 32: + return metaAccess.lookupJavaType(Float.TYPE); + case 64: + return metaAccess.lookupJavaType(Double.TYPE); + default: + throw GraalInternalError.shouldNotReachHere(); + } + } + + /** + * The (inclusive) lower bound on the value described by this stamp. + */ + public double lowerBound() { + return lowerBound; + } + + /** + * The (inclusive) upper bound on the value described by this stamp. + */ + public double upperBound() { + return upperBound; + } + + public boolean isNonNaN() { + return nonNaN; + } + + public boolean isUnrestricted() { + return lowerBound == Double.NEGATIVE_INFINITY && upperBound == Double.POSITIVE_INFINITY && !nonNaN; + } + + public boolean contains(double value) { + if (Double.isNaN(value)) { + return !nonNaN; + } else { + return value >= lowerBound && value <= upperBound; + } + } + + @Override + public String toString() { + StringBuilder str = new StringBuilder(); + str.append('f'); + str.append(getBits()); + str.append(nonNaN ? "!" : ""); + if (lowerBound == upperBound) { + str.append(" [").append(lowerBound).append(']'); + } else if (lowerBound != Double.NEGATIVE_INFINITY || upperBound != Double.POSITIVE_INFINITY) { + str.append(" [").append(lowerBound).append(" - ").append(upperBound).append(']'); + } + return str.toString(); + } + + @Override + public Stamp meet(Stamp otherStamp) { + if (otherStamp == this) { + return this; + } + if (!(otherStamp instanceof FloatStamp)) { + return StampFactory.illegal(Kind.Illegal); + } + FloatStamp other = (FloatStamp) otherStamp; + assert getBits() == other.getBits(); + double meetUpperBound = Math.max(upperBound, other.upperBound); + double meetLowerBound = Math.min(lowerBound, other.lowerBound); + boolean meetNonNaN = nonNaN && other.nonNaN; + if (meetLowerBound == lowerBound && meetUpperBound == upperBound && meetNonNaN == nonNaN) { + return this; + } else if (meetLowerBound == other.lowerBound && meetUpperBound == other.upperBound && meetNonNaN == other.nonNaN) { + return other; + } else { + return new FloatStamp(getBits(), meetLowerBound, meetUpperBound, meetNonNaN); + } + } + + @Override + public Stamp join(Stamp otherStamp) { + if (otherStamp == this) { + return this; + } + if (!(otherStamp instanceof FloatStamp)) { + return StampFactory.illegal(Kind.Illegal); + } + FloatStamp other = (FloatStamp) otherStamp; + assert getBits() == other.getBits(); + double joinUpperBound = Math.min(upperBound, other.upperBound); + double joinLowerBound = Math.max(lowerBound, other.lowerBound); + boolean joinNonNaN = nonNaN || other.nonNaN; + if (joinLowerBound == lowerBound && joinUpperBound == upperBound && joinNonNaN == nonNaN) { + return this; + } else if (joinLowerBound == other.lowerBound && joinUpperBound == other.upperBound && joinNonNaN == other.nonNaN) { + return other; + } else { + return new FloatStamp(getBits(), joinLowerBound, joinUpperBound, joinNonNaN); + } + } + + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + long temp; + result = prime * result + super.hashCode(); + temp = Double.doubleToLongBits(lowerBound); + result = prime * result + (int) (temp ^ (temp >>> 32)); + result = prime * result + (nonNaN ? 1231 : 1237); + temp = Double.doubleToLongBits(upperBound); + result = prime * result + (int) (temp ^ (temp >>> 32)); + return result; + } + + @Override + public boolean isCompatible(Stamp stamp) { + if (this == stamp) { + return true; + } + if (stamp instanceof FloatStamp) { + FloatStamp other = (FloatStamp) stamp; + return getBits() == other.getBits(); + } + return false; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) { + return true; + } + if (obj == null || getClass() != obj.getClass() || !super.equals(obj)) { + return false; + } + FloatStamp other = (FloatStamp) obj; + if (Double.doubleToLongBits(lowerBound) != Double.doubleToLongBits(other.lowerBound)) { + return false; + } + if (Double.doubleToLongBits(upperBound) != Double.doubleToLongBits(other.upperBound)) { + return false; + } + if (nonNaN != other.nonNaN) { + return false; + } + return true; + } + + @Override + public Constant asConstant() { + if (nonNaN && lowerBound == upperBound) { + switch (getBits()) { + case 32: + return Constant.forFloat((float) lowerBound); + case 64: + return Constant.forDouble(lowerBound); + } + } + return null; + } +} diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.compiler.common/src/com/oracle/graal/compiler/common/type/IllegalStamp.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.compiler.common/src/com/oracle/graal/compiler/common/type/IllegalStamp.java Mon Apr 28 11:18:15 2014 +0200 @@ -0,0 +1,92 @@ +/* + * Copyright (c) 2012, 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.graal.compiler.common.type; + +import com.oracle.graal.api.meta.*; +import com.oracle.graal.compiler.common.*; +import com.oracle.graal.compiler.common.spi.*; + +/** + * This stamp represents the illegal type. Values with this type can not exist at run time. + */ +public final class IllegalStamp extends Stamp { + + private IllegalStamp() { + } + + @Override + public Kind getStackKind() { + return Kind.Illegal; + } + + @Override + public PlatformKind getPlatformKind(PlatformKindTool tool) { + throw GraalInternalError.shouldNotReachHere("illegal stamp should not reach backend"); + } + + @Override + public Stamp unrestricted() { + return this; + } + + @Override + public Stamp illegal() { + return this; + } + + @Override + public ResolvedJavaType javaType(MetaAccessProvider metaAccess) { + throw GraalInternalError.shouldNotReachHere("illegal stamp has no Java type"); + } + + @Override + public Stamp meet(Stamp other) { + return this; + } + + @Override + public Stamp join(Stamp other) { + return this; + } + + @Override + public boolean isCompatible(Stamp stamp) { + return false; + } + + @Override + public String toString() { + return "ILLEGAL"; + } + + @Override + public boolean isLegal() { + return false; + } + + private static IllegalStamp instance = new IllegalStamp(); + + static IllegalStamp getInstance() { + return instance; + } +} diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.compiler.common/src/com/oracle/graal/compiler/common/type/IntegerStamp.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.compiler.common/src/com/oracle/graal/compiler/common/type/IntegerStamp.java Mon Apr 28 11:18:15 2014 +0200 @@ -0,0 +1,318 @@ +/* + * Copyright (c) 2012, 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.graal.compiler.common.type; + +import java.util.*; + +import com.oracle.graal.api.meta.*; +import com.oracle.graal.compiler.common.*; +import com.oracle.graal.compiler.common.spi.*; + +/** + * Describes the possible values of a {@link ValueNode} that produces an int or long result. + * + * The description consists of (inclusive) lower and upper bounds and up (may be set) and down + * (always set) bit-masks. + */ +@SuppressWarnings("javadoc") +public class IntegerStamp extends PrimitiveStamp { + + private final long lowerBound; + private final long upperBound; + private final long downMask; + private final long upMask; + + public IntegerStamp(int bits, long lowerBound, long upperBound, long downMask, long upMask) { + super(bits); + this.lowerBound = lowerBound; + this.upperBound = upperBound; + this.downMask = downMask; + this.upMask = upMask; + assert lowerBound >= defaultMinValue(bits) : this; + assert upperBound <= defaultMaxValue(bits) : this; + assert (downMask & defaultMask(bits)) == downMask : this; + assert (upMask & defaultMask(bits)) == upMask : this; + } + + @Override + public Stamp unrestricted() { + return new IntegerStamp(getBits(), defaultMinValue(getBits()), defaultMaxValue(getBits()), 0, defaultMask(getBits())); + } + + @Override + public Stamp illegal() { + return new IntegerStamp(getBits(), defaultMaxValue(getBits()), defaultMinValue(getBits()), defaultMask(getBits()), 0); + } + + @Override + public boolean isLegal() { + return lowerBound <= upperBound; + } + + @Override + public Kind getStackKind() { + if (getBits() > 32) { + return Kind.Long; + } else { + return Kind.Int; + } + } + + @Override + public PlatformKind getPlatformKind(PlatformKindTool tool) { + return tool.getIntegerKind(getBits()); + } + + @Override + public ResolvedJavaType javaType(MetaAccessProvider metaAccess) { + switch (getBits()) { + case 1: + return metaAccess.lookupJavaType(Boolean.TYPE); + case 8: + return metaAccess.lookupJavaType(Byte.TYPE); + case 16: + return metaAccess.lookupJavaType(Short.TYPE); + case 32: + return metaAccess.lookupJavaType(Integer.TYPE); + case 64: + return metaAccess.lookupJavaType(Long.TYPE); + default: + throw GraalInternalError.shouldNotReachHere(); + } + } + + /** + * The signed inclusive lower bound on the value described by this stamp. + */ + public long lowerBound() { + return lowerBound; + } + + /** + * The signed inclusive upper bound on the value described by this stamp. + */ + public long upperBound() { + return upperBound; + } + + /** + * This bit-mask describes the bits that are always set in the value described by this stamp. + */ + public long downMask() { + return downMask; + } + + /** + * This bit-mask describes the bits that can be set in the value described by this stamp. + */ + public long upMask() { + return upMask; + } + + public boolean isUnrestricted() { + return lowerBound == defaultMinValue(getBits()) && upperBound == defaultMaxValue(getBits()) && downMask == 0 && upMask == defaultMask(getBits()); + } + + public boolean contains(long value) { + return value >= lowerBound && value <= upperBound && (value & downMask) == downMask && (value & upMask) == (value & defaultMask(getBits())); + } + + public boolean isPositive() { + return lowerBound() >= 0; + } + + public boolean isNegative() { + return upperBound() <= 0; + } + + public boolean isStrictlyPositive() { + return lowerBound() > 0; + } + + public boolean isStrictlyNegative() { + return upperBound() < 0; + } + + public boolean canBePositive() { + return upperBound() > 0; + } + + public boolean canBeNegative() { + return lowerBound() < 0; + } + + @Override + public String toString() { + StringBuilder str = new StringBuilder(); + str.append('i'); + str.append(getBits()); + if (lowerBound == upperBound) { + str.append(" [").append(lowerBound).append(']'); + } else if (lowerBound != defaultMinValue(getBits()) || upperBound != defaultMaxValue(getBits())) { + str.append(" [").append(lowerBound).append(" - ").append(upperBound).append(']'); + } + if (downMask != 0) { + str.append(" \u21ca"); + new Formatter(str).format("%016x", downMask); + } + if (upMask != defaultMask(getBits())) { + str.append(" \u21c8"); + new Formatter(str).format("%016x", upMask); + } + return str.toString(); + } + + private Stamp createStamp(IntegerStamp other, long newUpperBound, long newLowerBound, long newDownMask, long newUpMask) { + assert getBits() == other.getBits(); + if (newLowerBound > newUpperBound || (newDownMask & (~newUpMask)) != 0) { + return illegal(); + } else if (newLowerBound == lowerBound && newUpperBound == upperBound && newDownMask == downMask && newUpMask == upMask) { + return this; + } else if (newLowerBound == other.lowerBound && newUpperBound == other.upperBound && newDownMask == other.downMask && newUpMask == other.upMask) { + return other; + } else { + return new IntegerStamp(getBits(), newLowerBound, newUpperBound, newDownMask, newUpMask); + } + } + + @Override + public Stamp meet(Stamp otherStamp) { + if (otherStamp == this) { + return this; + } + if (!(otherStamp instanceof IntegerStamp)) { + return StampFactory.illegal(Kind.Illegal); + } + IntegerStamp other = (IntegerStamp) otherStamp; + return createStamp(other, Math.max(upperBound, other.upperBound), Math.min(lowerBound, other.lowerBound), downMask & other.downMask, upMask | other.upMask); + } + + @Override + public Stamp join(Stamp otherStamp) { + if (otherStamp == this) { + return this; + } + if (!(otherStamp instanceof IntegerStamp)) { + return StampFactory.illegal(Kind.Illegal); + } + IntegerStamp other = (IntegerStamp) otherStamp; + long newDownMask = downMask | other.downMask; + long newLowerBound = Math.max(lowerBound, other.lowerBound) | newDownMask; + return createStamp(other, Math.min(upperBound, other.upperBound), newLowerBound, newDownMask, upMask & other.upMask); + } + + @Override + public boolean isCompatible(Stamp stamp) { + if (this == stamp) { + return true; + } + if (stamp instanceof IntegerStamp) { + IntegerStamp other = (IntegerStamp) stamp; + return getBits() == other.getBits(); + } + return false; + } + + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + super.hashCode(); + result = prime * result + (int) (lowerBound ^ (lowerBound >>> 32)); + result = prime * result + (int) (upperBound ^ (upperBound >>> 32)); + result = prime * result + (int) (downMask ^ (downMask >>> 32)); + result = prime * result + (int) (upMask ^ (upMask >>> 32)); + return result; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) { + return true; + } + if (obj == null || getClass() != obj.getClass() || !super.equals(obj)) { + return false; + } + IntegerStamp other = (IntegerStamp) obj; + if (lowerBound != other.lowerBound || upperBound != other.upperBound || downMask != other.downMask || upMask != other.upMask) { + return false; + } + return true; + } + + public static long defaultMask(int bits) { + assert 0 <= bits && bits <= 64; + if (bits == 64) { + return 0xffffffffffffffffL; + } else { + return (1L << bits) - 1; + } + } + + public static long defaultMinValue(int bits) { + return -1L << (bits - 1); + } + + public static long defaultMaxValue(int bits) { + return defaultMask(bits - 1); + } + + public static long upMaskFor(int bits, long lowerBound, long upperBound) { + long mask = lowerBound | upperBound; + if (mask == 0) { + return 0; + } else { + return ((-1L) >>> Long.numberOfLeadingZeros(mask)) & defaultMask(bits); + } + } + + /** + * Checks if the 2 stamps represent values of the same sign. Returns true if the two stamps are + * both positive of null or if they are both strictly negative + * + * @return true if the two stamps are both positive of null or if they are both strictly + * negative + */ + public static boolean sameSign(IntegerStamp s1, IntegerStamp s2) { + return s1.isPositive() && s2.isPositive() || s1.isStrictlyNegative() && s2.isStrictlyNegative(); + } + + @Override + public Constant asConstant() { + if (lowerBound == upperBound) { + switch (getBits()) { + case 1: + return Constant.forBoolean(lowerBound != 0); + case 8: + return Constant.forByte((byte) lowerBound); + case 16: + return Constant.forShort((short) lowerBound); + case 32: + return Constant.forInt((int) lowerBound); + case 64: + return Constant.forLong(lowerBound); + } + } + return null; + } +} diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.compiler.common/src/com/oracle/graal/compiler/common/type/ObjectStamp.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.compiler.common/src/com/oracle/graal/compiler/common/type/ObjectStamp.java Mon Apr 28 11:18:15 2014 +0200 @@ -0,0 +1,297 @@ +/* + * Copyright (c) 2012, 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.graal.compiler.common.type; + +import java.util.*; + +import com.oracle.graal.api.meta.*; +import com.oracle.graal.compiler.common.spi.*; + +public class ObjectStamp extends Stamp { + + private final ResolvedJavaType type; + private final boolean exactType; + private final boolean nonNull; + private final boolean alwaysNull; + + public ObjectStamp(ResolvedJavaType type, boolean exactType, boolean nonNull, boolean alwaysNull) { + this.type = type; + this.exactType = exactType; + this.nonNull = nonNull; + this.alwaysNull = alwaysNull; + } + + @Override + public Stamp unrestricted() { + return StampFactory.object(); + } + + @Override + public Stamp illegal() { + return new ObjectStamp(null, true, true, false); + } + + @Override + public boolean isLegal() { + return !exactType || (type != null && (isConcreteType(type))); + } + + @Override + public Kind getStackKind() { + return Kind.Object; + } + + @Override + public PlatformKind getPlatformKind(PlatformKindTool tool) { + return tool.getObjectKind(); + } + + @Override + public ResolvedJavaType javaType(MetaAccessProvider metaAccess) { + if (type != null) { + return type; + } + return metaAccess.lookupJavaType(Object.class); + } + + public boolean nonNull() { + return nonNull; + } + + public boolean alwaysNull() { + return alwaysNull; + } + + public ResolvedJavaType type() { + return type; + } + + public boolean isExactType() { + return exactType; + } + + @Override + public String toString() { + StringBuilder str = new StringBuilder(); + str.append('a'); + str.append(nonNull ? "!" : "").append(exactType ? "#" : "").append(' ').append(type == null ? "-" : type.getName()).append(alwaysNull ? " NULL" : ""); + return str.toString(); + } + + @Override + public Stamp meet(Stamp otherStamp) { + if (this == otherStamp) { + return this; + } + if (!(otherStamp instanceof ObjectStamp)) { + return StampFactory.illegal(Kind.Illegal); + } + ObjectStamp other = (ObjectStamp) otherStamp; + ResolvedJavaType meetType; + boolean meetExactType; + boolean meetNonNull; + boolean meetAlwaysNull; + if (other.alwaysNull) { + meetType = type(); + meetExactType = exactType; + meetNonNull = false; + meetAlwaysNull = alwaysNull; + } else if (alwaysNull) { + meetType = other.type(); + meetExactType = other.exactType; + meetNonNull = false; + meetAlwaysNull = other.alwaysNull; + } else { + meetType = meetTypes(type(), other.type()); + meetExactType = exactType && other.exactType; + if (meetExactType && type != null && other.type != null) { + // meeting two valid exact types may result in a non-exact type + meetExactType = Objects.equals(meetType, type) && Objects.equals(meetType, other.type); + } + meetNonNull = nonNull && other.nonNull; + meetAlwaysNull = false; + } + + if (Objects.equals(meetType, type) && meetExactType == exactType && meetNonNull == nonNull && meetAlwaysNull == alwaysNull) { + return this; + } else if (Objects.equals(meetType, other.type) && meetExactType == other.exactType && meetNonNull == other.nonNull && meetAlwaysNull == other.alwaysNull) { + return other; + } else { + return new ObjectStamp(meetType, meetExactType, meetNonNull, meetAlwaysNull); + } + } + + @Override + public Stamp join(Stamp otherStamp) { + return join0(otherStamp, false); + } + + @Override + public boolean isCompatible(Stamp other) { + if (this == other) { + return true; + } + if (other instanceof ObjectStamp) { + return true; + } + return false; + } + + /** + * Returns the stamp representing the type of this stamp after a cast to the type represented by + * the {@code to} stamp. While this is very similar to a {@link #join} operation, in the case + * where both types are not obviously related, the cast operation will prefer the type of the + * {@code to} stamp. This is necessary as long as ObjectStamps are not able to accurately + * represent intersection types. + * + * For example when joining the {@link RandomAccess} type with the {@link AbstractList} type, + * without intersection types, this would result in the most generic type ({@link Object} ). For + * this reason, in some cases a {@code castTo} operation is preferable in order to keep at least + * the {@link AbstractList} type. + * + * @param to the stamp this stamp should be casted to + * @return This stamp casted to the {@code to} stamp + */ + public Stamp castTo(ObjectStamp to) { + return join0(to, true); + } + + private Stamp join0(Stamp otherStamp, boolean castToOther) { + if (this == otherStamp) { + return this; + } + if (!(otherStamp instanceof ObjectStamp)) { + return StampFactory.illegal(Kind.Illegal); + } + ObjectStamp other = (ObjectStamp) otherStamp; + if (!isLegal()) { + return this; + } else if (!other.isLegal()) { + return other; + } + + ResolvedJavaType joinType; + boolean joinAlwaysNull = alwaysNull || other.alwaysNull; + boolean joinNonNull = nonNull || other.nonNull; + boolean joinExactType = exactType || other.exactType; + if (Objects.equals(type, other.type)) { + joinType = type; + } else if (type == null && other.type == null) { + joinType = null; + } else if (type == null) { + joinType = other.type; + } else if (other.type == null) { + joinType = type; + } else { + // both types are != null and different + if (type.isAssignableFrom(other.type)) { + joinType = other.type; + if (exactType) { + joinAlwaysNull = true; + } + } else if (other.type.isAssignableFrom(type)) { + joinType = type; + if (other.exactType) { + joinAlwaysNull = true; + } + } else { + if (castToOther) { + joinType = other.type; + joinExactType = other.exactType; + } else { + joinType = null; + } + if (joinExactType || (!type.isInterface() && !other.type.isInterface())) { + joinAlwaysNull = true; + } + } + } + if (joinAlwaysNull) { + joinType = null; + joinExactType = false; + } + if (joinExactType && joinType == null) { + return StampFactory.illegal(Kind.Object); + } + if (joinAlwaysNull && joinNonNull) { + return StampFactory.illegal(Kind.Object); + } else if (joinExactType && !isConcreteType(joinType)) { + return StampFactory.illegal(Kind.Object); + } + if (Objects.equals(joinType, type) && joinExactType == exactType && joinNonNull == nonNull && joinAlwaysNull == alwaysNull) { + return this; + } else if (Objects.equals(joinType, other.type) && joinExactType == other.exactType && joinNonNull == other.nonNull && joinAlwaysNull == other.alwaysNull) { + return other; + } else { + return new ObjectStamp(joinType, joinExactType, joinNonNull, joinAlwaysNull); + } + } + + public static boolean isConcreteType(ResolvedJavaType type) { + return !(type.isAbstract() && !type.isArray()); + } + + private static ResolvedJavaType meetTypes(ResolvedJavaType a, ResolvedJavaType b) { + if (Objects.equals(a, b)) { + return a; + } else if (a == null || b == null) { + return null; + } else { + return a.findLeastCommonAncestor(b); + } + } + + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + (exactType ? 1231 : 1237); + result = prime * result + (nonNull ? 1231 : 1237); + result = prime * result + (alwaysNull ? 1231 : 1237); + result = prime * result + ((type == null) ? 0 : type.hashCode()); + return result; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) { + return true; + } + if (obj == null || getClass() != obj.getClass()) { + return false; + } + ObjectStamp other = (ObjectStamp) obj; + if (exactType != other.exactType || nonNull != other.nonNull || alwaysNull != other.alwaysNull) { + return false; + } + if (type == null) { + if (other.type != null) { + return false; + } + } else if (!type.equals(other.type)) { + return false; + } + return true; + } + +} diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.compiler.common/src/com/oracle/graal/compiler/common/type/PrimitiveStamp.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.compiler.common/src/com/oracle/graal/compiler/common/type/PrimitiveStamp.java Mon Apr 28 11:18:15 2014 +0200 @@ -0,0 +1,71 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.graal.compiler.common.type; + +/** + * Describes the possible values of a {@link ValueNode} that produces a primitive value as result. + */ +@SuppressWarnings("javadoc") +public abstract class PrimitiveStamp extends Stamp { + + private final int bits; + + protected PrimitiveStamp(int bits) { + this.bits = bits; + } + + /** + * The width in bits of the value described by this stamp. + */ + public int getBits() { + return bits; + } + + public static int getBits(Stamp stamp) { + if (stamp instanceof PrimitiveStamp) { + return ((PrimitiveStamp) stamp).getBits(); + } else { + return 0; + } + } + + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + bits; + return result; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) { + return true; + } + if (obj instanceof PrimitiveStamp) { + PrimitiveStamp other = (PrimitiveStamp) obj; + return bits == other.bits; + } + return false; + } +} diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.compiler.common/src/com/oracle/graal/compiler/common/type/Stamp.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.compiler.common/src/com/oracle/graal/compiler/common/type/Stamp.java Mon Apr 28 11:18:15 2014 +0200 @@ -0,0 +1,111 @@ +/* + * Copyright (c) 2011, 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.graal.compiler.common.type; + +import com.oracle.graal.api.meta.*; +import com.oracle.graal.compiler.common.spi.*; + +/** + * A stamp is the basis for a type system over the nodes in a graph. + */ +public abstract class Stamp { + + protected Stamp() { + } + + /** + * Returns the type of the stamp, guaranteed to be non-null. In some cases, this requires the + * lookup of class meta data, therefore the {@link MetaAccessProvider} is mandatory. + */ + public abstract ResolvedJavaType javaType(MetaAccessProvider metaAccess); + + public boolean alwaysDistinct(Stamp other) { + return !join(other).isLegal(); + } + + /** + * Gets a Java {@link Kind} that can be used to store a value of this stamp on the Java bytecode + * stack. Returns {@link Kind#Illegal} if a value of this stamp can not be stored on the + * bytecode stack. + */ + public abstract Kind getStackKind(); + + /** + * Gets a platform dependent {@link PlatformKind} that can be used to store a value of this + * stamp. + */ + public abstract PlatformKind getPlatformKind(PlatformKindTool tool); + + /** + * Returns the union of this stamp and the given stamp. Typically used to create stamps for + * {@link ValuePhiNode}s. + * + * @param other The stamp that will enlarge this stamp. + * @return The union of this stamp and the given stamp. + */ + @SuppressWarnings("javadoc") + public abstract Stamp meet(Stamp other); + + /** + * Returns the intersection of this stamp and the given stamp. + * + * @param other The stamp that will tighten this stamp. + * @return The intersection of this stamp and the given stamp. + */ + public abstract Stamp join(Stamp other); + + /** + * Returns a stamp of the same kind, but allowing the full value range of the kind. + * + * {@link #unrestricted()} is the neutral element of the {@link #join(Stamp)} operation. + */ + public abstract Stamp unrestricted(); + + /** + * Returns a stamp of the same kind, but with no allowed values. + * + * {@link #illegal()} is the neutral element of the {@link #meet(Stamp)} operation. + */ + public abstract Stamp illegal(); + + /** + * Test whether two stamps have the same base type. + */ + public abstract boolean isCompatible(Stamp other); + + /** + * Test whether this stamp has legal values. + */ + public abstract boolean isLegal(); + + /** + * If this stamp represents a single value, the methods returns this single value. It returns + * null otherwise. + * + * @return the constant corresponding to the single value of this stamp and null if this stamp + * can represent less or more than one value. + */ + public Constant asConstant() { + return null; + } +} diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.compiler.common/src/com/oracle/graal/compiler/common/type/StampFactory.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.compiler.common/src/com/oracle/graal/compiler/common/type/StampFactory.java Mon Apr 28 11:18:15 2014 +0200 @@ -0,0 +1,254 @@ +/* + * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.graal.compiler.common.type; + +import com.oracle.graal.api.meta.*; +import com.oracle.graal.compiler.common.*; + +public class StampFactory { + + // JaCoCo Exclude + + private static final Stamp[] stampCache = new Stamp[Kind.values().length]; + private static final Stamp[] illegalStampCache = new Stamp[Kind.values().length]; + private static final Stamp objectStamp = new ObjectStamp(null, false, false, false); + private static final Stamp objectNonNullStamp = new ObjectStamp(null, false, true, false); + private static final Stamp objectAlwaysNullStamp = new ObjectStamp(null, false, false, true); + private static final Stamp nodeIntrinsicStamp = new ObjectStamp(null, false, false, false); + private static final Stamp positiveInt = forInteger(Kind.Int, 0, Integer.MAX_VALUE, 0, Integer.MAX_VALUE); + + private static void setCache(Kind kind, Stamp stamp) { + stampCache[kind.ordinal()] = stamp; + } + + private static void setIntCache(Kind kind) { + int bits = kind.getStackKind().getBitCount(); + long mask; + if (kind.isUnsigned()) { + mask = IntegerStamp.defaultMask(kind.getBitCount()); + } else { + mask = IntegerStamp.defaultMask(bits); + } + setCache(kind, new IntegerStamp(bits, kind.getMinValue(), kind.getMaxValue(), 0, mask)); + } + + private static void setFloatCache(Kind kind) { + setCache(kind, new FloatStamp(kind.getBitCount())); + } + + static { + setIntCache(Kind.Boolean); + setIntCache(Kind.Byte); + setIntCache(Kind.Short); + setIntCache(Kind.Char); + setIntCache(Kind.Int); + setIntCache(Kind.Long); + + setFloatCache(Kind.Float); + setFloatCache(Kind.Double); + + setCache(Kind.Object, objectStamp); + setCache(Kind.Void, VoidStamp.getInstance()); + + for (Kind k : Kind.values()) { + if (stampCache[k.ordinal()] != null) { + illegalStampCache[k.ordinal()] = stampCache[k.ordinal()].illegal(); + } else { + illegalStampCache[k.ordinal()] = IllegalStamp.getInstance(); + } + } + } + + /** + * Return a stamp for a Java kind, as it would be represented on the bytecode stack. + */ + public static Stamp forKind(Kind kind) { + assert stampCache[kind.ordinal()] != null : "unexpected forKind(" + kind + ")"; + return stampCache[kind.ordinal()]; + } + + /** + * Return the stamp for the {@code void} type. This will return a singleton instance than can be + * compared using {@code ==}. + */ + public static Stamp forVoid() { + return VoidStamp.getInstance(); + } + + /** + * A stamp used only in the graph of intrinsics, e.g., snippets. It is then replaced by an + * actual stamp when the intrinsic is used, i.e., when the snippet template is instantiated. + */ + public static Stamp forNodeIntrinsic() { + return nodeIntrinsicStamp; + } + + public static Stamp intValue() { + return forKind(Kind.Int); + } + + public static Stamp positiveInt() { + return positiveInt; + } + + public static Stamp illegal() { + return illegal(Kind.Illegal); + } + + public static Stamp illegal(Kind kind) { + return illegalStampCache[kind.ordinal()]; + } + + public static IntegerStamp forInteger(Kind kind, long lowerBound, long upperBound, long downMask, long upMask) { + return new IntegerStamp(kind.getBitCount(), lowerBound, upperBound, downMask, upMask); + } + + public static IntegerStamp forInteger(Kind kind, long lowerBound, long upperBound) { + return forInteger(kind.getBitCount(), lowerBound, upperBound); + } + + public static IntegerStamp forInteger(int bits) { + return new IntegerStamp(bits, IntegerStamp.defaultMinValue(bits), IntegerStamp.defaultMaxValue(bits), 0, IntegerStamp.defaultMask(bits)); + } + + public static IntegerStamp forInteger(int bits, long lowerBound, long upperBound) { + long defaultMask = IntegerStamp.defaultMask(bits); + if (lowerBound == upperBound) { + return new IntegerStamp(bits, lowerBound, lowerBound, lowerBound & defaultMask, lowerBound & defaultMask); + } + final long downMask; + final long upMask; + if (lowerBound >= 0) { + int upperBoundLeadingZeros = Long.numberOfLeadingZeros(upperBound); + long differentBits = lowerBound ^ upperBound; + int sameBitCount = Long.numberOfLeadingZeros(differentBits << upperBoundLeadingZeros); + + upMask = upperBound | -1L >>> (upperBoundLeadingZeros + sameBitCount); + downMask = upperBound & ~(-1L >>> (upperBoundLeadingZeros + sameBitCount)); + } else { + if (upperBound >= 0) { + upMask = defaultMask; + downMask = 0; + } else { + int lowerBoundLeadingOnes = Long.numberOfLeadingZeros(~lowerBound); + long differentBits = lowerBound ^ upperBound; + int sameBitCount = Long.numberOfLeadingZeros(differentBits << lowerBoundLeadingOnes); + + upMask = lowerBound | -1L >>> (lowerBoundLeadingOnes + sameBitCount) | ~(-1L >>> lowerBoundLeadingOnes); + downMask = lowerBound & ~(-1L >>> (lowerBoundLeadingOnes + sameBitCount)) | ~(-1L >>> lowerBoundLeadingOnes); + } + } + return new IntegerStamp(bits, lowerBound, upperBound, downMask & defaultMask, upMask & defaultMask); + } + + public static FloatStamp forFloat(Kind kind, double lowerBound, double upperBound, boolean nonNaN) { + assert kind.isNumericFloat(); + return new FloatStamp(kind.getBitCount(), lowerBound, upperBound, nonNaN); + } + + public static Stamp forConstant(Constant value) { + Kind kind = value.getKind(); + switch (kind) { + case Boolean: + case Byte: + case Char: + case Short: + case Int: + case Long: + long mask = value.asLong() & IntegerStamp.defaultMask(kind.getBitCount()); + return forInteger(kind.getStackKind(), value.asLong(), value.asLong(), mask, mask); + case Float: + return forFloat(kind, value.asFloat(), value.asFloat(), !Float.isNaN(value.asFloat())); + case Double: + return forFloat(kind, value.asDouble(), value.asDouble(), !Double.isNaN(value.asDouble())); + case Illegal: + return illegal(Kind.Illegal); + case Object: + if (value.isNull()) { + return alwaysNull(); + } else { + return objectNonNull(); + } + default: + throw new GraalInternalError("unexpected kind: %s", kind); + } + } + + public static Stamp forConstant(Constant value, MetaAccessProvider metaAccess) { + assert value.getKind() == Kind.Object; + if (value.getKind() == Kind.Object) { + ResolvedJavaType type = value.isNull() ? null : metaAccess.lookupJavaType(value); + return new ObjectStamp(type, value.isNonNull(), value.isNonNull(), value.isNull()); + } else { + throw new GraalInternalError(Kind.Object + " expected, actual kind: %s", value.getKind()); + } + } + + public static Stamp object() { + return objectStamp; + } + + public static Stamp objectNonNull() { + return objectNonNullStamp; + } + + public static Stamp alwaysNull() { + return objectAlwaysNullStamp; + } + + public static Stamp declared(ResolvedJavaType type) { + return declared(type, false); + } + + public static Stamp declaredNonNull(ResolvedJavaType type) { + return declared(type, true); + } + + public static Stamp declared(ResolvedJavaType type, boolean nonNull) { + return object(type, false, nonNull); + } + + public static Stamp object(ResolvedJavaType type, boolean exactType, boolean nonNull) { + assert type != null; + assert type.getKind() == Kind.Object; + ResolvedJavaType exact = type.asExactType(); + if (exact != null) { + assert !exactType || type.equals(exact); + return new ObjectStamp(exact, true, nonNull, false); + } else { + return new ObjectStamp(type, exactType, nonNull, false); + } + } + + public static Stamp exactNonNull(ResolvedJavaType type) { + if (ObjectStamp.isConcreteType(type)) { + return new ObjectStamp(type, true, true, false); + } else { + return illegal(Kind.Object); + } + } + + public static Stamp exact(ResolvedJavaType type) { + return new ObjectStamp(type, true, false, false); + } +} diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.compiler.common/src/com/oracle/graal/compiler/common/type/StampProvider.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.compiler.common/src/com/oracle/graal/compiler/common/type/StampProvider.java Mon Apr 28 11:18:15 2014 +0200 @@ -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.compiler.common.type; + +public interface StampProvider { + + Stamp stamp(); +} diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.compiler.common/src/com/oracle/graal/compiler/common/type/VoidStamp.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.compiler.common/src/com/oracle/graal/compiler/common/type/VoidStamp.java Mon Apr 28 11:18:15 2014 +0200 @@ -0,0 +1,110 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.graal.compiler.common.type; + +import com.oracle.graal.api.meta.*; +import com.oracle.graal.compiler.common.*; +import com.oracle.graal.compiler.common.spi.*; + +/** + * Singleton stamp representing the value of type {@code void}. + */ +public final class VoidStamp extends Stamp { + + private VoidStamp() { + } + + @Override + public Stamp unrestricted() { + return this; + } + + @Override + public Kind getStackKind() { + return Kind.Void; + } + + @Override + public PlatformKind getPlatformKind(PlatformKindTool tool) { + throw GraalInternalError.shouldNotReachHere("void stamp has no value"); + } + + @Override + public ResolvedJavaType javaType(MetaAccessProvider metaAccess) { + return metaAccess.lookupJavaType(Void.TYPE); + } + + @Override + public String toString() { + return "void"; + } + + @Override + public boolean alwaysDistinct(Stamp other) { + return this != other; + } + + @Override + public Stamp meet(Stamp other) { + if (other instanceof IllegalStamp) { + return other.join(this); + } + if (this == other) { + return this; + } + return StampFactory.illegal(Kind.Illegal); + } + + @Override + public Stamp join(Stamp other) { + if (other instanceof IllegalStamp) { + return other.join(this); + } + if (this == other) { + return this; + } + return StampFactory.illegal(Kind.Illegal); + } + + @Override + public boolean isCompatible(Stamp stamp) { + return this == stamp; + } + + @Override + public Stamp illegal() { + // there is no illegal void stamp + return this; + } + + @Override + public boolean isLegal() { + return true; + } + + private static VoidStamp instance = new VoidStamp(); + + static VoidStamp getInstance() { + return instance; + } +} diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.compiler.hsail.test.infra/src/com/oracle/graal/compiler/hsail/test/infra/GraalKernelTester.java --- a/graal/com.oracle.graal.compiler.hsail.test.infra/src/com/oracle/graal/compiler/hsail/test/infra/GraalKernelTester.java Fri Apr 25 16:21:07 2014 +0200 +++ b/graal/com.oracle.graal.compiler.hsail.test.infra/src/com/oracle/graal/compiler/hsail/test/infra/GraalKernelTester.java Mon Apr 28 11:18:15 2014 +0200 @@ -27,8 +27,8 @@ * This class extends KernelTester and provides a base class * for which the HSAIL code comes from the Graal compiler. */ +import static com.oracle.graal.compiler.common.GraalOptions.*; import static com.oracle.graal.hotspot.HotSpotGraalRuntime.*; -import static com.oracle.graal.phases.GraalOptions.*; import static org.junit.Assume.*; import java.io.*; @@ -38,16 +38,15 @@ import com.oracle.graal.api.code.*; import com.oracle.graal.api.meta.*; +import com.oracle.graal.compiler.common.*; import com.oracle.graal.compiler.target.*; import com.oracle.graal.debug.*; import com.oracle.graal.gpu.*; -import com.oracle.graal.graph.*; import com.oracle.graal.hotspot.hsail.*; import com.oracle.graal.hotspot.meta.*; import com.oracle.graal.hsail.*; import com.oracle.graal.options.*; import com.oracle.graal.options.OptionValue.OverrideScope; -import com.oracle.graal.phases.*; public abstract class GraalKernelTester extends KernelTester { @@ -103,6 +102,40 @@ return (canGenerateCalls && canExecuteCalls); } + private static boolean supportsObjectAllocation() { + return true; + } + + /** + * Determines if the runtime supports object allocation in HSAIL code. + */ + public boolean canHandleObjectAllocation() { + return supportsObjectAllocation() && canDeoptimize(); + } + + /** + * Determines if the runtime supports deoptimization in HSAIL code. + */ + public boolean canDeoptimize() { + return getHSAILBackend().getRuntime().getConfig().useHSAILDeoptimization; + } + + /** + * Determines if the runtime supports {@link VirtualObject}s in {@link DebugInfo} associated + * with HSAIL code. + */ + public boolean canHandleDeoptVirtualObjects() { + return false; + } + + /** + * Determines if the runtime supports {@link StackSlot}s in {@link DebugInfo} associated with + * HSAIL code. + */ + public boolean canHandleDeoptStackSlots() { + return false; + } + /** * Determines if the runtime has the capabilities required by this test. */ @@ -156,8 +189,8 @@ @Override public void testGeneratedHsailUsingLambdaMethod() { try (OverrideScope s = getOverrideScope()) { + assumeTrue(supportsRequiredCapabilities()); super.testGeneratedHsailUsingLambdaMethod(); } } - } diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.compiler.hsail.test.infra/src/com/oracle/graal/compiler/hsail/test/infra/KernelTester.java --- a/graal/com.oracle.graal.compiler.hsail.test.infra/src/com/oracle/graal/compiler/hsail/test/infra/KernelTester.java Fri Apr 25 16:21:07 2014 +0200 +++ b/graal/com.oracle.graal.compiler.hsail.test.infra/src/com/oracle/graal/compiler/hsail/test/infra/KernelTester.java Mon Apr 28 11:18:15 2014 +0200 @@ -416,9 +416,9 @@ } /** - * The dispatchLambdaKernel dispatches the lambda version of a kernel where the "kernel" is for - * the xxx$$Lambda.accept method in the wrapper for the lambda. Note that the useLambdaMethod - * boolean provides a way of actually invoking dispatchLambdaMethodKernel from this API. + * Dispatches the lambda version of a kernel where the "kernel" is for the xxx$$Lambda.accept + * method in the wrapper for the lambda. Note that the useLambdaMethod boolean provides a way of + * actually invoking dispatchLambdaMethodKernel from this API. */ public void dispatchLambdaKernel(int range, MyIntConsumer consumer) { if (useLambdaMethod) { diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/AtomicIntGetAndAddTest.java --- a/graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/AtomicIntGetAndAddTest.java Fri Apr 25 16:21:07 2014 +0200 +++ b/graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/AtomicIntGetAndAddTest.java Mon Apr 28 11:18:15 2014 +0200 @@ -27,13 +27,10 @@ import org.junit.*; -import sun.misc.*; - import com.oracle.graal.compiler.hsail.test.infra.*; /** - * Tests {@link AtomicInteger#getAndAdd(int)} which indirectly tests - * {@link Unsafe#compareAndSwapInt(Object, long, int, int)}. + * Tests {@link AtomicInteger#getAndAdd(int)} which tests HSAIL atomic_add codegen. */ public class AtomicIntGetAndAddTest extends GraalKernelTester { diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/AtomicIntGetAndSetTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/AtomicIntGetAndSetTest.java Mon Apr 28 11:18:15 2014 +0200 @@ -0,0 +1,72 @@ +/* + * 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.compiler.hsail.test; + +import java.util.*; +import java.util.concurrent.atomic.*; + +import org.junit.*; + +import com.oracle.graal.compiler.hsail.test.infra.*; + +/** + * Tests {@link AtomicInteger#getAndSet(int)} which tests HSAIL atomic_exch codegen. + */ +public class AtomicIntGetAndSetTest extends GraalKernelTester { + + static final int NUM = 1000; + @Result public int[] outArray = new int[NUM]; + AtomicInteger atomicInt = new AtomicInteger(Integer.MAX_VALUE); + + void setupArrays() { + for (int i = 0; i < NUM; i++) { + outArray[i] = -i; + } + } + + @Override + public void runTest() { + setupArrays(); + + dispatchMethodKernel(NUM); + // to complete the circle, replace the initial get value with that of the last executor + for (int i = 0; i < NUM; i++) { + if (outArray[i] == Integer.MAX_VALUE) { + outArray[i] = atomicInt.get(); + } + } + + // note: the actual order of entries in outArray is not predictable + // thus we sort before we compare results + Arrays.sort(outArray); + } + + public void run(int gid) { + outArray[gid] = atomicInt.getAndSet(gid); + } + + @Test + public void test() { + testGeneratedHsail(); + } +} diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/AtomicLongGetAndAddTest.java --- a/graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/AtomicLongGetAndAddTest.java Fri Apr 25 16:21:07 2014 +0200 +++ b/graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/AtomicLongGetAndAddTest.java Mon Apr 28 11:18:15 2014 +0200 @@ -27,13 +27,10 @@ import org.junit.*; -import sun.misc.*; - import com.oracle.graal.compiler.hsail.test.infra.*; /** - * Tests {@link AtomicLong#getAndAdd(long)} which indirectly tests - * {@link Unsafe#compareAndSwapLong(Object, long, long, long)}. + * Tests {@link AtomicLong#getAndAdd(long)} which tests HSAIL atomic_add codegen. */ public class AtomicLongGetAndAddTest extends GraalKernelTester { diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/AtomicLongGetAndSetTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/AtomicLongGetAndSetTest.java Mon Apr 28 11:18:15 2014 +0200 @@ -0,0 +1,72 @@ +/* + * 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.compiler.hsail.test; + +import java.util.*; +import java.util.concurrent.atomic.*; + +import org.junit.*; + +import com.oracle.graal.compiler.hsail.test.infra.*; + +/** + * Tests {@link AtomicLong#getAndSet(long)} which tests HSAIL atomic_exch codegen. + */ +public class AtomicLongGetAndSetTest extends GraalKernelTester { + + static final int NUM = 1000; + @Result public long[] outArray = new long[NUM]; + AtomicLong atomicLong = new AtomicLong(Long.MAX_VALUE); + + void setupArrays() { + for (int i = 0; i < NUM; i++) { + outArray[i] = -i; + } + } + + @Override + public void runTest() { + setupArrays(); + + dispatchMethodKernel(NUM); + // to complete the circle, replace the initial get value with that of the last executor + for (int i = 0; i < NUM; i++) { + if (outArray[i] == Long.MAX_VALUE) { + outArray[i] = atomicLong.get(); + } + } + + // note: the actual order of entries in outArray is not predictable + // thus we sort before we compare results + Arrays.sort(outArray); + } + + public void run(int gid) { + outArray[gid] = atomicLong.getAndSet(gid); + } + + @Test + public void test() { + testGeneratedHsail(); + } +} diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/AtomicReferenceGetAndSetTest.java diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/BasicHSAILTest.java --- a/graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/BasicHSAILTest.java Fri Apr 25 16:21:07 2014 +0200 +++ b/graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/BasicHSAILTest.java Mon Apr 28 11:18:15 2014 +0200 @@ -22,6 +22,8 @@ */ package com.oracle.graal.compiler.hsail.test; +import static com.oracle.graal.debug.DelegatingDebugConfig.Feature.*; + import java.lang.reflect.*; import org.junit.*; @@ -343,12 +345,14 @@ } private void test(final String snippet) { - try (Scope s = Debug.scope("HSAILCodeGen")) { - Method method = getMethod(snippet); - ExternalCompilationResult hsailCode = getBackend().compileKernel(getMetaAccess().lookupJavaMethod(method), false); - Debug.log("HSAIL code generated for %s:%n%s", snippet, hsailCode.getCodeString()); - } catch (Throwable e) { - throw Debug.handle(e); + try (DebugConfigScope dcs = Debug.setConfig(new DelegatingDebugConfig().disable(INTERCEPT))) { + try (Scope s = Debug.scope("HSAILCodeGen")) { + Method method = getMethod(snippet); + ExternalCompilationResult hsailCode = getBackend().compileKernel(getMetaAccess().lookupJavaMethod(method), false); + Debug.log("HSAIL code generated for %s:%n%s", snippet, hsailCode.getCodeString()); + } catch (Throwable e) { + throw Debug.handle(e); + } } } diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/BoundsCatchBase.java --- a/graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/BoundsCatchBase.java Fri Apr 25 16:21:07 2014 +0200 +++ b/graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/BoundsCatchBase.java Mon Apr 28 11:18:15 2014 +0200 @@ -56,7 +56,7 @@ @Override protected boolean supportsRequiredCapabilities() { - return getHSAILBackend().getRuntime().getConfig().useHSAILDeoptimization; + return canDeoptimize(); } @Override diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/EscapingNewBase.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/EscapingNewBase.java Mon Apr 28 11:18:15 2014 +0200 @@ -0,0 +1,81 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.graal.compiler.hsail.test; + +import com.oracle.graal.compiler.hsail.test.infra.GraalKernelTester; +import java.util.Arrays; + +/** + * Base Class for tests that allocate escaping objects. + */ + +public class EscapingNewBase extends GraalKernelTester { + + final int NUM = getRange(); + + int getRange() { + return 24; + } + + @Result public Object[] outArray = new Object[NUM]; + public Object[] savedOutArray; + @Result public boolean savedOutArrayMatch1; + @Result public boolean savedOutArrayMatch2; + @Result public boolean savedOutArrayMatch3; + + void setupArrays() { + for (int i = 0; i < NUM; i++) { + outArray[i] = null; + } + } + + int getDispatches() { + return 1; + } + + @Override + protected boolean supportsRequiredCapabilities() { + return canHandleObjectAllocation(); + } + + @Override + public void runTest() { + setupArrays(); + + dispatchMethodKernel(NUM); + // use System.gc() to ensure new objects are in form that gc likes + System.gc(); + savedOutArray = Arrays.copyOf(outArray, NUM); + savedOutArrayMatch1 = Arrays.equals(outArray, savedOutArray); + if (getDispatches() > 1) { + // redispatch kernel without gc + dispatchMethodKernel(NUM); + savedOutArrayMatch2 = Arrays.equals(outArray, savedOutArray); + // and one more time with gc + dispatchMethodKernel(NUM); + savedOutArrayMatch3 = Arrays.equals(outArray, savedOutArray); + System.gc(); + } + } + +} diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/EscapingNewFloatStringTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/EscapingNewFloatStringTest.java Mon Apr 28 11:18:15 2014 +0200 @@ -0,0 +1,45 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.graal.compiler.hsail.test; + +import org.junit.*; + +/** + * Tests creating a new String from a float. + */ + +public class EscapingNewFloatStringTest extends EscapingNewBase { + + @Result public String[] myOutArray = new String[NUM]; + + public void run(int gid) { + outArray[gid] = Float.toString(gid * 1.11f); + myOutArray[gid] = Float.toString(gid * 2.22f); + } + + @Ignore("problems runs out of memory space while inlining") + @Test + public void test() { + testGeneratedHsail(); + } +} diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/EscapingNewFloatTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/EscapingNewFloatTest.java Mon Apr 28 11:18:15 2014 +0200 @@ -0,0 +1,40 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.graal.compiler.hsail.test; + +import org.junit.Test; + +public class EscapingNewFloatTest extends EscapingNewBase { + @Result Float[] myOutArray = new Float[NUM]; + + public void run(int gid) { + outArray[gid] = (gid + 1) * 1.11f; + myOutArray[gid] = (gid + 1) * 2.22f; + } + + @Test + public void test() { + testGeneratedHsail(); + } + +} diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/EscapingNewIntArrayTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/EscapingNewIntArrayTest.java Mon Apr 28 11:18:15 2014 +0200 @@ -0,0 +1,63 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.graal.compiler.hsail.test; + +import org.junit.Test; + +/** + * Tests allocation of an integer array per workitem. + */ + +public class EscapingNewIntArrayTest extends EscapingNewBase { + + public void run(int gid) { + int size = gid + 1; + int[] ary = new int[size]; + for (int i = 0; i < ary.length; i++) { + ary[i] = i * 3; + } + outArray[gid] = ary; + } + + private static final boolean DEBUG = Boolean.getBoolean("hsail.debug"); + + @Override + public void runTest() { + super.runTest(); + if (DEBUG) { + for (int i = 0; i < NUM; i++) { + int[] ary = (int[]) outArray[i]; + System.out.print("ary len " + ary.length + ": "); + for (int val : ary) { + System.out.print(val + ","); + } + System.out.println(); + } + } + } + + @Test + public void test() { + testGeneratedHsail(); + } +} diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/EscapingNewIntegerTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/EscapingNewIntegerTest.java Mon Apr 28 11:18:15 2014 +0200 @@ -0,0 +1,44 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.graal.compiler.hsail.test; + +import org.junit.Test; + +/** + * Tests allocation of a java.lang.Integer per workitem. + */ + +public class EscapingNewIntegerTest extends EscapingNewBase { + @Result Integer[] myOutArray = new Integer[NUM]; + + public void run(int gid) { + outArray[gid] = (gid + 1) * 111; + myOutArray[gid] = (gid + 1) * 222; + } + + @Test + public void test() { + testGeneratedHsail(); + } + +} diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/EscapingNewStoreFieldTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/EscapingNewStoreFieldTest.java Mon Apr 28 11:18:15 2014 +0200 @@ -0,0 +1,72 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.graal.compiler.hsail.test; + +import com.oracle.graal.compiler.hsail.test.infra.GraalKernelTester; +import org.junit.Test; + +/** + * Tests allocation of a Vec3 object stored in a field by workitem #1. + */ + +public class EscapingNewStoreFieldTest extends GraalKernelTester { + + static final int NUM = 20; + public float[] inArray = new float[NUM]; + @Result public Vec3 outField; + + void setupArrays() { + for (int i = 0; i < NUM; i++) { + inArray[i] = i; + } + } + + public void run(int gid) { + if (gid == 1) { + float inval = inArray[gid]; + outField = new Vec3(inval + 1, inval + 2, inval + 3); + } + } + + @Override + public void runTest() { + setupArrays(); + + dispatchMethodKernel(NUM); + + // see what happens if we do it again + dispatchMethodKernel(NUM); + System.gc(); + } + + @Override + protected boolean supportsRequiredCapabilities() { + return canHandleObjectAllocation(); + } + + @Test + public void test() { + testGeneratedHsail(); + } + +} diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/EscapingNewStringConcatTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/EscapingNewStringConcatTest.java Mon Apr 28 11:18:15 2014 +0200 @@ -0,0 +1,60 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.graal.compiler.hsail.test; + +import static com.oracle.graal.debug.Debug.*; + +import org.junit.Test; + +import com.oracle.graal.debug.*; + +/** + * Tests allocation of a new String based on string concatenation. + */ + +public class EscapingNewStringConcatTest extends EscapingNewBase { + + @Result public String[] myOutArray = new String[NUM]; + public String[] inArray = new String[NUM]; + + @Override + void setupArrays() { + super.setupArrays(); + for (int i = 0; i < NUM; i++) { + inArray[i] = Integer.toString(i + 100); + } + } + + public void run(int gid) { + outArray[gid] = inArray[gid] + inArray[(gid + NUM / 2) % NUM]; + myOutArray[gid] = inArray[(gid + NUM / 2) % NUM] + inArray[gid]; + } + + // Node implementing Lowerable not handled in HSAIL Backend: 6274|MonitorEnter + @Test(expected = com.oracle.graal.compiler.common.GraalInternalError.class) + public void test() { + try (DebugConfigScope s = disableIntercept()) { + testGeneratedHsail(); + } + } +} diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/EscapingNewStringInternTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/EscapingNewStringInternTest.java Mon Apr 28 11:18:15 2014 +0200 @@ -0,0 +1,48 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.graal.compiler.hsail.test; + +import static com.oracle.graal.debug.Debug.*; + +import org.junit.Test; + +import com.oracle.graal.debug.*; + +/** + * Tests allocation of a new String based on string interning. + */ + +public class EscapingNewStringInternTest extends EscapingNewBase { + + public void run(int gid) { + outArray[gid] = Integer.toString(gid * 111).intern(); + } + + // at node: 12|Invoke#Direct#intern + @Test(expected = com.oracle.graal.compiler.common.GraalInternalError.class) + public void test() { + try (DebugConfigScope s = disableIntercept()) { + testGeneratedHsail(); + } + } +} diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/EscapingNewStringLargeRangeTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/EscapingNewStringLargeRangeTest.java Mon Apr 28 11:18:15 2014 +0200 @@ -0,0 +1,43 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.graal.compiler.hsail.test; + +import org.junit.Test; + +/** + * Tests allocation of a new String from integer with a large range of workitems. + */ + +public class EscapingNewStringLargeRangeTest extends EscapingNewStringTest { + + @Override + int getRange() { + return 125000; + } + + @Override + @Test + public void test() { + testGeneratedHsail(); + } +} diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/EscapingNewStringTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/EscapingNewStringTest.java Mon Apr 28 11:18:15 2014 +0200 @@ -0,0 +1,44 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.graal.compiler.hsail.test; + +import org.junit.Test; + +/** + * Tests allocation of a new String from an integer per workitem. + */ + +public class EscapingNewStringTest extends EscapingNewBase { + + @Result public String[] myOutArray = new String[NUM]; + + public void run(int gid) { + outArray[gid] = Integer.toString(gid * 111); + myOutArray[gid] = Integer.toString(gid * 222); + } + + @Test + public void test() { + testGeneratedHsail(); + } +} diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/EscapingNewVec3ArrayTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/EscapingNewVec3ArrayTest.java Mon Apr 28 11:18:15 2014 +0200 @@ -0,0 +1,64 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.graal.compiler.hsail.test; + +import org.junit.Test; + +/** + * Tests allocation of an array of Vec3 objects per workitem. + */ + +public class EscapingNewVec3ArrayTest extends EscapingNewBase { + + public void run(int gid) { + int size = gid + 1; + Vec3[] vec3ary = new Vec3[size]; + for (int i = 0; i < vec3ary.length; i++) { + vec3ary[i] = new Vec3(size + i + 1.1f, size + i + 2.2f, size + i + 3.3f); + } + outArray[gid] = vec3ary; + } + + private static final boolean DEBUG = Boolean.getBoolean("hsail.debug"); + + @Override + public void runTest() { + super.runTest(); + if (DEBUG) { + System.out.println("dumping results"); + for (int i = 0; i < NUM; i++) { + Vec3[] ary = (Vec3[]) outArray[i]; + System.out.print("ary len " + ary.length + ": "); + for (Vec3 val : ary) { + System.out.print(val + ", "); + } + System.out.println(); + } + } + } + + @Test + public void test() { + testGeneratedHsail(); + } +} diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/EscapingNewVec3Base.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/EscapingNewVec3Base.java Mon Apr 28 11:18:15 2014 +0200 @@ -0,0 +1,50 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.graal.compiler.hsail.test; + +/** + * Base class for Vec3 object allocation tests. + */ + +public class EscapingNewVec3Base extends EscapingNewBase { + + float[] inArray = new float[NUM]; + @Result Vec3[] myOutArray = new Vec3[NUM]; + + @Override + void setupArrays() { + super.setupArrays(); + for (int i = 0; i < NUM; i++) { + inArray[i] = i; + myOutArray[i] = null; + } + } + + public void run(int gid) { + float inval = inArray[gid]; + // allocate and store in Object array + outArray[gid] = new Vec3(inval + 1.1f, inval + 2.1f, inval + 3.1f); + // allocate and store in Vec3 array + myOutArray[gid] = new Vec3(inval + 4.1f, inval + 5.1f, inval + 6.1f); + } +} diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/EscapingNewVec3LargeRangeDisp3Test.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/EscapingNewVec3LargeRangeDisp3Test.java Mon Apr 28 11:18:15 2014 +0200 @@ -0,0 +1,49 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.graal.compiler.hsail.test; + +import org.junit.Test; + +/** + * Tests allocation of a new Vec3 object with a large range of workitems with 3 dispatches. + */ + +public class EscapingNewVec3LargeRangeDisp3Test extends EscapingNewVec3Test { + + @Override + int getRange() { + return 250000; + } + + @Override + int getDispatches() { + return 3; + } + + @Override + @Test + public void test() { + testGeneratedHsail(); + } + +} diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/EscapingNewVec3LargeRangeTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/EscapingNewVec3LargeRangeTest.java Mon Apr 28 11:18:15 2014 +0200 @@ -0,0 +1,44 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.graal.compiler.hsail.test; + +import org.junit.Test; + +/** + * Tests allocation of a new Vec3 object with a large range of workitems. + */ + +public class EscapingNewVec3LargeRangeTest extends EscapingNewVec3Test { + + @Override + int getRange() { + return 250000; + } + + @Override + @Test + public void test() { + testGeneratedHsail(); + } + +} diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/EscapingNewVec3MediumRangeTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/EscapingNewVec3MediumRangeTest.java Mon Apr 28 11:18:15 2014 +0200 @@ -0,0 +1,44 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.graal.compiler.hsail.test; + +import org.junit.Test; + +/** + * Tests allocation of a new Vec3 object with a medium range of workitems. + */ + +public class EscapingNewVec3MediumRangeTest extends EscapingNewVec3Test { + + @Override + int getRange() { + return 100000; + } + + @Override + @Test + public void test() { + testGeneratedHsail(); + } + +} diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/EscapingNewVec3Partial2Test.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/EscapingNewVec3Partial2Test.java Mon Apr 28 11:18:15 2014 +0200 @@ -0,0 +1,49 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.graal.compiler.hsail.test; + +import org.junit.Test; + +/** + * Tests allocation of a new Vec3 object but skipping one workitem. + */ + +public class EscapingNewVec3Partial2Test extends EscapingNewVec3Base { + + int testGid = NUM / 2; + + @Override + public void run(int gid) { + float inval = inArray[gid]; + if (gid != testGid) { + outArray[gid] = new Vec3(inval + 1.1f, inval + 2.1f, inval + 3.1f); + myOutArray[gid] = new Vec3(inval + 4.1f, inval + 5.1f, inval + 6.1f); + } + } + + @Test + public void test() { + testGeneratedHsail(); + } + +} diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/EscapingNewVec3PartialTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/EscapingNewVec3PartialTest.java Mon Apr 28 11:18:15 2014 +0200 @@ -0,0 +1,45 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.graal.compiler.hsail.test; + +import org.junit.Test; + +/** + * Tests allocation of a new Vec3 object but only for half of the workitems. + */ + +public class EscapingNewVec3PartialTest extends EscapingNewVec3Base { + + @Override + public void run(int gid) { + float inval = inArray[gid]; + outArray[gid] = (gid % 2 == 0 ? new Vec3(inval + 1.1f, inval + 2.1f, inval + 3.1f) : null); + myOutArray[gid] = (gid % 2 != 0 ? new Vec3(inval + 4.1f, inval + 5.1f, inval + 6.1f) : null); + } + + @Test + public void test() { + testGeneratedHsail(); + } + +} diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/EscapingNewVec3Test.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/EscapingNewVec3Test.java Mon Apr 28 11:18:15 2014 +0200 @@ -0,0 +1,38 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.graal.compiler.hsail.test; + +import org.junit.Test; + +/** + * Tests allocation of a new Vec3 object per workitem. + */ + +public class EscapingNewVec3Test extends EscapingNewVec3Base { + + @Test + public void test() { + testGeneratedHsail(); + } + +} diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/FloatSqrtTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/FloatSqrtTest.java Mon Apr 28 11:18:15 2014 +0200 @@ -0,0 +1,59 @@ +/* + * Copyright (c) 2009, 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.hsail.test; + +import org.junit.*; + +import com.oracle.graal.compiler.hsail.test.infra.*; + +/** + * Tests floating point square root. + */ +public class FloatSqrtTest extends GraalKernelTester { + + static final int size = 64; + float[] input = new float[size]; + @Result float[] output = new float[size]; + { + for (int i = 0; i < size; i++) { + input[i] = i; + output[i] = -1.0f; + } + + } + + public static void run(float[] input1, float[] output1, int gid) { + output1[gid] = (float) Math.sqrt(input1[gid]); + } + + @Override + public void runTest() { + dispatchMethodKernel(size, input, output); + } + + @Test + public void test() { + testGeneratedHsail(); + } +} diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/InstanceOfTwoLevelTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/InstanceOfTwoLevelTest.java Mon Apr 28 11:18:15 2014 +0200 @@ -0,0 +1,118 @@ +/* + * Copyright (c) 2009, 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.hsail.test; + +import com.oracle.graal.compiler.hsail.test.infra.GraalKernelTester; +import org.junit.Test; + +public class InstanceOfTwoLevelTest extends GraalKernelTester { + + static final int NUM = 20; + + static abstract class Shape { + abstract public float getArea(); + } + + static class Ellipse extends Shape { + private float major; + private float minor; + + Ellipse(float major, float minor) { + this.major = major; + this.minor = minor; + } + + public float getEccentricity() { + float a = major / 2; + float b = minor / 2; + return (float) Math.sqrt(1 - (b / a) * (b / a)); + } + + @Override + public float getArea() { + float a = major / 2; + float b = minor / 2; + return (float) (Math.PI * a * b); + } + } + + static class Circle extends Ellipse { + Circle(float r) { + super(2 * r, 2 * r); + } + } + + static class Square extends Shape { + private float len; + + Square(float _len) { + len = _len; + } + + @Override + public float getArea() { + return len * len; + } + } + + @Result public float[] outArray = new float[NUM]; + public Object[] inShapeArray = new Object[NUM]; + + void setupArrays() { + for (int i = 0; i < NUM; i++) { + switch (i % 4) { + case 0: + inShapeArray[i] = new Circle(i + 1); + break; + case 1: + inShapeArray[i] = new Square(i + 1); + break; + case 2: + inShapeArray[i] = new Ellipse(i + 1, i + 2); + break; + case 3: + inShapeArray[i] = new Object(); + break; + } + outArray[i] = -i; + } + } + + public void run(int gid) { + outArray[gid] = (inShapeArray[gid] instanceof Shape ? 1.0f : 2.0f); + } + + @Override + public void runTest() { + setupArrays(); + + dispatchMethodKernel(NUM); + } + + @Test + public void test() { + testGeneratedHsail(); + } + +} diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/IntTestBranchTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/IntTestBranchTest.java Mon Apr 28 11:18:15 2014 +0200 @@ -0,0 +1,52 @@ +/* + * Copyright (c) 2009, 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.hsail.test; + +import org.junit.Test; + +/** + * Tests code generation for IntegerTestNode for HSAIL backend. + */ +public class IntTestBranchTest extends StaticMethodTwoIntArrays { + + /** + * The static "kernel" method we will be testing. By convention the gid is the last parameter. + * + * @param out + * @param in + * @param gid + */ + public static void run(int[] out, int[] in, int gid) { + if ((in[gid] & 3) != 0) { + out[gid] = in[gid] * 2; + } else { + out[gid] = in[gid] * 3; + } + } + + @Test + public void test() { + super.testGeneratedHsail(); + } +} diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/NestedStaticCallTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/NestedStaticCallTest.java Mon Apr 28 11:18:15 2014 +0200 @@ -0,0 +1,85 @@ +/* + * Copyright (c) 2009, 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.hsail.test; + +import org.junit.*; + +import com.oracle.graal.compiler.hsail.test.infra.GraalKernelTester; + +/** + * Tests direct method calls. + */ +public class NestedStaticCallTest extends GraalKernelTester { + + static final int width = 768; + static final int height = width; + private int iterations = 100; + static final int range = width * height; + @Result public float[] outArray = new float[range]; + + public static int a(int i) { + if (i < 2) { + return b(i); + } else { + return i; + } + } + + public static int b(int i) { + if (i < 90) { + return c(i) + i; + } else { + return d(i) - i; + } + } + + public static int c(int i) { + + return d(i) + 5; + } + + public static int d(int i) { + + return e(i) + 10; + } + + public static int e(int i) { + return 52 + i; + } + + public void run(int gid) { + for (int i = 0; i < iterations; i++) { + outArray[gid] = a(gid) + i; + } + } + + @Override + public void runTest() { + dispatchMethodKernel(range); + } + + @Test + public void test() { + testGeneratedHsail(); + } +} diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/NestedVirtualCallTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/NestedVirtualCallTest.java Mon Apr 28 11:18:15 2014 +0200 @@ -0,0 +1,85 @@ +/* + * Copyright (c) 2009, 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.hsail.test; + +import org.junit.*; + +import com.oracle.graal.compiler.hsail.test.infra.GraalKernelTester; + +/** + * Tests direct method calls. + */ +public class NestedVirtualCallTest extends GraalKernelTester { + + static final int width = 768; + static final int height = width; + private int iterations = 100; + static final int range = width * height; + @Result public float[] outArray = new float[range]; + + public int a(int i) { + if (i < 2) { + return b(i); + } else { + return i; + } + } + + public int b(int i) { + if (i < 90) { + return c(i) + i; + } else { + return d(i) - i; + } + } + + public int c(int i) { + + return d(i) + 5; + } + + public int d(int i) { + + return e(i) + 10; + } + + public int e(int i) { + return 52 + i; + } + + public void run(int gid) { + for (int i = 0; i < iterations; i++) { + outArray[gid] = a(gid) + i; + } + } + + @Override + public void runTest() { + dispatchMethodKernel(range); + } + + @Test + public void test() { + super.testGeneratedHsail(); + } +} diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/SingleExceptionTestBase.java --- a/graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/SingleExceptionTestBase.java Fri Apr 25 16:21:07 2014 +0200 +++ b/graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/SingleExceptionTestBase.java Mon Apr 28 11:18:15 2014 +0200 @@ -37,7 +37,7 @@ @Override protected boolean supportsRequiredCapabilities() { - return getHSAILBackend().getRuntime().getConfig().useHSAILDeoptimization; + return canDeoptimize(); } void recordException(Exception e) { diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/StaticCallTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/StaticCallTest.java Mon Apr 28 11:18:15 2014 +0200 @@ -0,0 +1,71 @@ +/* + * Copyright (c) 2009, 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.hsail.test; + +import org.junit.*; + +import com.oracle.graal.compiler.hsail.test.infra.GraalKernelTester; + +/** + * Tests direct method calls. + */ +public class StaticCallTest extends GraalKernelTester { + + static final int width = 768; + static final int height = width; + private int iterations = 100; + static final int range = width * height; + @Result public float[] outArray = new float[range]; + + public static int foo(int gid, int i) { + if (gid < 2) { + return bar(gid, i); + } else { + return gid + i; + } + } + + public static int bar(int gid, int i) { + if (gid < 90) { + return gid + i; + } else { + return gid - i; + } + } + + public void run(int gid) { + for (int i = 0; i < iterations; i++) { + outArray[gid] = bar(gid, i); + } + } + + @Override + public void runTest() { + dispatchMethodKernel(range); + } + + @Test + public void test() { + super.testGeneratedHsail(); + } +} diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/StaticDoubleSpillTest.java --- a/graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/StaticDoubleSpillTest.java Fri Apr 25 16:21:07 2014 +0200 +++ b/graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/StaticDoubleSpillTest.java Mon Apr 28 11:18:15 2014 +0200 @@ -118,9 +118,8 @@ dispatchMethodKernel(size, out, in); } - // Marked to only run on hardware until simulator spill bug is fixed. - @Ignore @Test + @Ignore("until stack slots are supported in deopt") public void test() { testGeneratedHsail(); } diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/StaticIntSpillTest.java --- a/graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/StaticIntSpillTest.java Fri Apr 25 16:21:07 2014 +0200 +++ b/graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/StaticIntSpillTest.java Mon Apr 28 11:18:15 2014 +0200 @@ -87,9 +87,8 @@ dispatchMethodKernel(size, out, in); } - // Marked to only run on hardware until simulator spill bug is fixed. - @Ignore @Test + @Ignore("until stack slots are supported in deopt") public void test() { testGeneratedHsail(); } diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/StaticMandelBoundsCheckTest.java --- a/graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/StaticMandelBoundsCheckTest.java Fri Apr 25 16:21:07 2014 +0200 +++ b/graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/StaticMandelBoundsCheckTest.java Mon Apr 28 11:18:15 2014 +0200 @@ -23,8 +23,6 @@ package com.oracle.graal.compiler.hsail.test; -import static org.junit.Assume.*; - import org.junit.*; /** @@ -84,7 +82,6 @@ @Test public void test() { - assumeTrue(runningOnSimulator()); testGeneratedHsail(); } } diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/StaticMandelTest.java --- a/graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/StaticMandelTest.java Fri Apr 25 16:21:07 2014 +0200 +++ b/graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/StaticMandelTest.java Mon Apr 28 11:18:15 2014 +0200 @@ -23,10 +23,7 @@ package com.oracle.graal.compiler.hsail.test; -import static org.junit.Assume.*; - import org.junit.*; - import com.oracle.graal.compiler.hsail.test.infra.*; /** @@ -82,7 +79,6 @@ @Test public void test() { - assumeTrue(runningOnSimulator()); testGeneratedHsail(); } } diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/StaticMethod16InArraysTest.java --- a/graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/StaticMethod16InArraysTest.java Fri Apr 25 16:21:07 2014 +0200 +++ b/graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/StaticMethod16InArraysTest.java Mon Apr 28 11:18:15 2014 +0200 @@ -23,10 +23,11 @@ package com.oracle.graal.compiler.hsail.test; +import static com.oracle.graal.debug.DelegatingDebugConfig.Feature.*; + import org.junit.*; import com.oracle.graal.debug.*; -import com.oracle.graal.debug.internal.*; /** * Tests the addition of elements from sixteen input arrays. @@ -64,15 +65,7 @@ @Test(expected = java.lang.ClassCastException.class) @Ignore("until GPU backends can co-exist") public void test() { - DebugConfig debugConfig = DebugScope.getConfig(); - DebugConfig noInterceptConfig = new DelegatingDebugConfig(debugConfig) { - @Override - public RuntimeException interceptException(Throwable e) { - return null; - } - }; - - try (DebugConfigScope s = Debug.setConfig(noInterceptConfig)) { + try (DebugConfigScope s = Debug.setConfig(new DelegatingDebugConfig().disable(INTERCEPT))) { testGeneratedHsail(); } } diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/StaticNBodyCallTest.java --- a/graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/StaticNBodyCallTest.java Fri Apr 25 16:21:07 2014 +0200 +++ b/graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/StaticNBodyCallTest.java Mon Apr 28 11:18:15 2014 +0200 @@ -23,8 +23,6 @@ package com.oracle.graal.compiler.hsail.test; -import static org.junit.Assume.*; - import org.junit.*; /** @@ -39,7 +37,6 @@ @Override public void runTest() { - assumeTrue(aggressiveInliningEnabled() || canHandleHSAILMethodCalls()); super.runTest(); } diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/StringContainsAcceptTest.java --- a/graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/StringContainsAcceptTest.java Fri Apr 25 16:21:07 2014 +0200 +++ b/graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/StringContainsAcceptTest.java Mon Apr 28 11:18:15 2014 +0200 @@ -23,8 +23,6 @@ package com.oracle.graal.compiler.hsail.test; -import static org.junit.Assume.*; - import org.junit.*; /** @@ -42,7 +40,6 @@ @Override public void runTest() { - assumeTrue(aggressiveInliningEnabled() || canHandleHSAILMethodCalls()); setupArrays(); dispatchMethodKernel(NUM); diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/StringSwitchTest.java --- a/graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/StringSwitchTest.java Fri Apr 25 16:21:07 2014 +0200 +++ b/graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/StringSwitchTest.java Mon Apr 28 11:18:15 2014 +0200 @@ -23,11 +23,9 @@ package com.oracle.graal.compiler.hsail.test; -import static org.junit.Assume.*; - import org.junit.*; -import com.oracle.graal.compiler.hsail.test.infra.*; +import com.oracle.graal.compiler.hsail.test.infra.GraalKernelTester; /** * Tests switch statement with String literal keys. @@ -121,14 +119,8 @@ } } - /** - * Tests the HSAIL code generated for this unit test by comparing the result of executing this - * code with the result of executing a sequential Java version of this unit test. - */ @Test public void test() { - // This test is only run if inlining is enabled since it requires method call support. - assumeTrue(aggressiveInliningEnabled() || canHandleHSAILMethodCalls()); super.testGeneratedHsail(); } diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/VolatileIntTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/VolatileIntTest.java Mon Apr 28 11:18:15 2014 +0200 @@ -0,0 +1,75 @@ +/* + * Copyright (c) 2009, 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.hsail.test; + +import com.oracle.graal.compiler.hsail.test.infra.GraalKernelTester; +import org.junit.Test; + +/** + * + * @author ecaspole + */ +public class VolatileIntTest extends GraalKernelTester { + + static final int num = 20; + @Result protected int[] outArray = new int[num]; + + volatile int theVolatileInt = 42; + + /** + * The static "kernel" method we will be testing. By convention the gid is the last parameter. + * + */ + public void run(int[] out, int[] ina, int[] inb, int gid) { + + // Note these array ops are not really part of the test results + int x = theVolatileInt; + + out[gid] = ina[gid] + inb[gid]; + + theVolatileInt = x; + } + + @Test + public void test() { + super.testGeneratedHsail(); + } + + void setupArrays(int[] in, int[] in2) { + for (int i = 0; i < num; i++) { + in[i] = 1; + in2[i] = 2; + outArray[i] = 0; + } + } + + @Override + public void runTest() { + int[] inArray = new int[num]; + int[] inArray2 = new int[num]; + setupArrays(inArray, inArray2); + + dispatchMethodKernel(num, outArray, inArray, inArray2); + } + +} diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/lambda/ArrayFieldAccessTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/lambda/ArrayFieldAccessTest.java Mon Apr 28 11:18:15 2014 +0200 @@ -0,0 +1,64 @@ +/* + * Copyright (c) 2009, 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.hsail.test.lambda; + +import com.oracle.graal.compiler.hsail.test.infra.GraalKernelTester; +import org.junit.Test; + +/** + * Tests accessing a field which is an array. + */ +public class ArrayFieldAccessTest extends GraalKernelTester { + + static final int NUM = 20; + @Result public int[] outArray = new int[NUM]; + public int[] inArray = new int[NUM]; + + void setupArrays() { + for (int i = 0; i < NUM; i++) { + inArray[i] = i; + outArray[i] = -i; + } + } + + @Override + public void runTest() { + setupArrays(); + + dispatchLambdaKernel(NUM, (gid) -> { + outArray[gid] = inArray[gid] * 3; + }); + } + + @Test + public void test() { + testGeneratedHsail(); + } + + @Test + public void testUsingLambdaMethod() { + testGeneratedHsailUsingLambdaMethod(); + } + +} diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/lambda/ArrayListGetTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/lambda/ArrayListGetTest.java Mon Apr 28 11:18:15 2014 +0200 @@ -0,0 +1,69 @@ +/* + * Copyright (c) 2009, 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.hsail.test.lambda; + +import static com.oracle.graal.debug.Debug.*; + +import com.oracle.graal.compiler.hsail.test.infra.GraalKernelTester; +import com.oracle.graal.debug.*; + +import org.junit.Test; + +import java.util.ArrayList; + +/** + * Tests calling ArrayList.get(). + */ +public class ArrayListGetTest extends GraalKernelTester { + + static final int NUM = 20; + @Result public int[] outArray = new int[NUM]; + public ArrayList inList = new ArrayList<>(); + + void setupArrays() { + for (int i = 0; i < NUM; i++) { + inList.add(i); + outArray[i] = -i; + } + } + + @Override + public void runTest() { + setupArrays(); + + dispatchLambdaKernel(NUM, (gid) -> { + int val = inList.get(gid); + outArray[gid] = val * val + 1; + }); + } + + // NYI emitForeignCall charAlignedDisjointArraycopy + @Test(expected = com.oracle.graal.compiler.common.GraalInternalError.class) + public void testUsingLambdaMethod() { + try (DebugConfigScope s = disableIntercept()) { + testGeneratedHsailUsingLambdaMethod(); + } + } + +} diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/lambda/ArrayListStreamTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/lambda/ArrayListStreamTest.java Mon Apr 28 11:18:15 2014 +0200 @@ -0,0 +1,190 @@ +/* + * Copyright (c) 2009, 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.hsail.test.lambda; + +import java.util.ArrayList; +import java.util.stream.Stream; +import static org.junit.Assert.assertTrue; +import org.junit.Test; + +/** + * Tests using ArrayLists as streams. + */ +public class ArrayListStreamTest { + + // Static and instance fields to test codegen for + // each type of variable + static int staticSize = 16; + final int size = staticSize; + + static int staticFactor = 3; + final int factor = staticFactor; + + class MyPoint { + + int x; + int y; + + public MyPoint(int _x, int _y) { + x = _x; + y = _y; + } + } + + public ArrayList buildMyPointInputArray() { + ArrayList inputs = new ArrayList<>(size); + + for (int i = 0; i < size; i++) { + inputs.add(new MyPoint(i, i + 1)); + } + return inputs; + } + + public int[] buildIntInputArray() { + int[] inputs = new int[size]; + + for (int i = 0; i < size; i++) { + inputs[i] = i * 4; + } + return inputs; + } + + @Test + public void testForEachObjectStreamNoCaptures() { + ArrayList inputs = buildMyPointInputArray(); + + Stream s = inputs.stream(); + s = s.parallel(); + s.forEach(p -> { + // Swap the values + int tmp = p.x; + p.x = p.y + factor; + p.y = tmp; + }); + + for (int k = 0; k < size; k++) { + MyPoint p = inputs.get(k); + // System.out.println( k + " ... p.x=" + p.x ); + assertTrue(p.x == (p.y + 1 + factor)); + } + } + + @Test + public void testForEachObjectStreamNoCapturesUseStatic() { + ArrayList inputs = buildMyPointInputArray(); + + Stream s = inputs.stream(); + s = s.parallel(); + s.forEach(p -> { + // Swap the values + int tmp = p.x; + p.x = p.y + staticFactor; + p.y = tmp; + }); + + for (int k = 0; k < size; k++) { + MyPoint p = inputs.get(k); + // System.out.println( k + " ... p.x=" + p.x ); + assertTrue(p.x == (p.y + 1 + staticFactor)); + } + } + + @Test + public void testForEachObjectStreamOneCapture() { + int[] data = buildIntInputArray(); + ArrayList inputs = buildMyPointInputArray(); + + Stream s = inputs.stream(); + s = s.parallel(); + s.forEach(p -> { + p.y = data[p.x]; + }); + + for (int k = 0; k < size; k++) { + MyPoint p = inputs.get(k); + // System.out.println( k + " ... p.x=" + p.x ); + assertTrue(p.y == data[p.x]); + } + + } + + @Test + public void testForEachObjectStreamOneCaptureUseStatic() { + int[] data = buildIntInputArray(); + ArrayList inputs = buildMyPointInputArray(); + + Stream s = inputs.stream(); + s = s.parallel(); + s.forEach(p -> { + p.y = data[p.x] + staticFactor; + }); + + for (int k = 0; k < size; k++) { + MyPoint p = inputs.get(k); + // System.out.println( k + " ... p.x=" + p.x ); + assertTrue(p.y == (data[p.x] + +staticFactor)); + } + + } + + @Test + public void testForEachObjectStreamTwoCaptures() { + int[] data = buildIntInputArray(); + int[] data2 = buildIntInputArray(); + ArrayList inputs = buildMyPointInputArray(); + + Stream s = inputs.stream(); + s = s.parallel(); + s.forEach(p -> { + p.y = data[p.x] + data2[p.x]; + }); + + for (int k = 0; k < size; k++) { + MyPoint p = inputs.get(k); + // System.out.println( k + " ... p.x=" + p.x ); + assertTrue(p.y == data[p.x] + data2[p.x]); + } + + } + + @Test + public void testForEachObjectStreamTwoCapturesUseStatic() { + int[] data = buildIntInputArray(); + int[] data2 = buildIntInputArray(); + ArrayList inputs = buildMyPointInputArray(); + + Stream s = inputs.stream(); + s = s.parallel(); + s.forEach(p -> { + p.y = data[p.x] + data2[p.x] + staticFactor; + }); + + for (int k = 0; k < size; k++) { + MyPoint p = inputs.get(k); + // System.out.println( k + " ... p.x=" + p.x ); + assertTrue(p.y == data[p.x] + data2[p.x] + staticFactor); + } + + } +} diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/lambda/AtomicIntAddAndGetGidTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/lambda/AtomicIntAddAndGetGidTest.java Mon Apr 28 11:18:15 2014 +0200 @@ -0,0 +1,84 @@ +/* + * Copyright (c) 2009, 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.hsail.test.lambda; + +import com.oracle.graal.compiler.hsail.test.infra.GraalKernelTester; +import org.junit.Test; + +import java.util.concurrent.atomic.AtomicInteger; +import java.util.Arrays; + +/** + * Tests {@link AtomicInteger#addAndGet(int)} with a variable delta. + */ +public class AtomicIntAddAndGetGidTest extends GraalKernelTester { + + static final int NUM = 20; + public int[] outArray = new int[NUM]; + @Result public int[] gaps = new int[NUM]; + AtomicInteger atomicInt; + + void setupArrays() { + for (int i = 0; i < NUM; i++) { + outArray[i] = -i; + } + atomicInt = new AtomicInteger(0); + } + + @Override + public void runTest() { + setupArrays(); + + dispatchLambdaKernel(NUM, (gid) -> { + outArray[gid] = atomicInt.addAndGet(gid); + }); + + // note: the actual order of entries in outArray is not predictable + // thus we sort before we compare results + Arrays.sort(outArray); + // System.out.print("outArray: "); + // for (int val : outArray) { + // System.out.print(val + ", "); + // } + // System.out.println(); + // create array of gaps + gaps[0] = outArray[0] - 0; + for (int i = 1; i < NUM; i++) { + gaps[i] = outArray[i] - outArray[i - 1]; + } + Arrays.sort(gaps); + + } + + @Test + public void test() { + testGeneratedHsail(); + } + + @Test + public void testUsingLambdaMethod() { + testGeneratedHsailUsingLambdaMethod(); + } + +} diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/lambda/AtomicIntAddAndGetTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/lambda/AtomicIntAddAndGetTest.java Mon Apr 28 11:18:15 2014 +0200 @@ -0,0 +1,69 @@ +/* + * Copyright (c) 2009, 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.hsail.test.lambda; + +import com.oracle.graal.compiler.hsail.test.infra.GraalKernelTester; +import org.junit.Test; +import java.util.concurrent.atomic.AtomicInteger; +import java.util.Arrays; + +/** + * Tests {@link AtomicInteger#addAndGet(int)} with the delta being a constant. + */ +public class AtomicIntAddAndGetTest extends GraalKernelTester { + + static final int NUM = 20; + @Result public int[] outArray = new int[NUM]; + AtomicInteger atomicInt = new AtomicInteger(); + + void setupArrays() { + for (int i = 0; i < NUM; i++) { + outArray[i] = -i; + } + } + + @Override + public void runTest() { + setupArrays(); + + dispatchLambdaKernel(NUM, (gid) -> { + outArray[gid] = atomicInt.addAndGet(0x7); + }); + + // note: the actual order of entries in outArray is not predictable + // thus we sort before we compare results + Arrays.sort(outArray); + } + + @Test + public void test() { + testGeneratedHsail(); + } + + @Test + public void testUsingLambdaMethod() { + testGeneratedHsailUsingLambdaMethod(); + } + +} diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/lambda/AtomicIntDecAndGetTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/lambda/AtomicIntDecAndGetTest.java Mon Apr 28 11:18:15 2014 +0200 @@ -0,0 +1,69 @@ +/* + * Copyright (c) 2009, 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.hsail.test.lambda; + +import com.oracle.graal.compiler.hsail.test.infra.GraalKernelTester; +import org.junit.Test; +import java.util.concurrent.atomic.AtomicInteger; +import java.util.Arrays; + +/** + * Tests {@link AtomicInteger#decrementAndGet()}. + */ +public class AtomicIntDecAndGetTest extends GraalKernelTester { + + static final int NUM = 20; + @Result public int[] outArray = new int[NUM]; + AtomicInteger atomicInt = new AtomicInteger(); + + void setupArrays() { + for (int i = 0; i < NUM; i++) { + outArray[i] = -i; + } + } + + @Override + public void runTest() { + setupArrays(); + + dispatchLambdaKernel(NUM, (gid) -> { + outArray[gid] = atomicInt.decrementAndGet(); + }); + + // note: the actual order of entries in outArray is not predictable + // thus we sort before we compare results + Arrays.sort(outArray); + } + + @Test + public void test() { + testGeneratedHsail(); + } + + @Test + public void testUsingLambdaMethod() { + testGeneratedHsailUsingLambdaMethod(); + } + +} diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/lambda/AtomicIntGetAndAddTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/lambda/AtomicIntGetAndAddTest.java Mon Apr 28 11:18:15 2014 +0200 @@ -0,0 +1,69 @@ +/* + * Copyright (c) 2009, 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.hsail.test.lambda; + +import com.oracle.graal.compiler.hsail.test.infra.GraalKernelTester; +import org.junit.Test; +import java.util.concurrent.atomic.AtomicInteger; +import java.util.Arrays; + +/** + * Tests {@link AtomicInteger#getAndAdd(int)} with the delta being a constant. + */ +public class AtomicIntGetAndAddTest extends GraalKernelTester { + + static final int NUM = 20; + @Result public int[] outArray = new int[NUM]; + AtomicInteger atomicInt = new AtomicInteger(); + + void setupArrays() { + for (int i = 0; i < NUM; i++) { + outArray[i] = -i; + } + } + + @Override + public void runTest() { + setupArrays(); + + dispatchLambdaKernel(NUM, (gid) -> { + outArray[gid] = atomicInt.getAndAdd(0x7); + }); + + // note: the actual order of entries in outArray is not predictable + // thus we sort before we compare results + Arrays.sort(outArray); + } + + @Test + public void test() { + testGeneratedHsail(); + } + + @Test + public void testUsingLambdaMethod() { + testGeneratedHsailUsingLambdaMethod(); + } + +} diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/lambda/AtomicIntGetAndDecTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/lambda/AtomicIntGetAndDecTest.java Mon Apr 28 11:18:15 2014 +0200 @@ -0,0 +1,69 @@ +/* + * Copyright (c) 2009, 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.hsail.test.lambda; + +import com.oracle.graal.compiler.hsail.test.infra.GraalKernelTester; +import org.junit.Test; +import java.util.concurrent.atomic.AtomicInteger; +import java.util.Arrays; + +/** + * Tests {@link AtomicInteger#getAndDecrement()}. + */ +public class AtomicIntGetAndDecTest extends GraalKernelTester { + + static final int NUM = 20; + @Result public int[] outArray = new int[NUM]; + AtomicInteger atomicInt = new AtomicInteger(); + + void setupArrays() { + for (int i = 0; i < NUM; i++) { + outArray[i] = -i; + } + } + + @Override + public void runTest() { + setupArrays(); + + dispatchLambdaKernel(NUM, (gid) -> { + outArray[gid] = atomicInt.getAndDecrement(); + }); + + // note: the actual order of entries in outArray is not predictable + // thus we sort before we compare results + Arrays.sort(outArray); + } + + @Test + public void test() { + testGeneratedHsail(); + } + + @Test + public void testUsingLambdaMethod() { + testGeneratedHsailUsingLambdaMethod(); + } + +} diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/lambda/AtomicIntGetAndIncTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/lambda/AtomicIntGetAndIncTest.java Mon Apr 28 11:18:15 2014 +0200 @@ -0,0 +1,69 @@ +/* + * Copyright (c) 2009, 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.hsail.test.lambda; + +import com.oracle.graal.compiler.hsail.test.infra.GraalKernelTester; +import org.junit.Test; +import java.util.concurrent.atomic.AtomicInteger; +import java.util.Arrays; + +/** + * Tests {@link AtomicInteger#getAndIncrement()}. + */ +public class AtomicIntGetAndIncTest extends GraalKernelTester { + + static final int NUM = 20; + @Result public int[] outArray = new int[NUM]; + AtomicInteger atomicInt = new AtomicInteger(); + + void setupArrays() { + for (int i = 0; i < NUM; i++) { + outArray[i] = -i; + } + } + + @Override + public void runTest() { + setupArrays(); + + dispatchLambdaKernel(NUM, (gid) -> { + outArray[gid] = atomicInt.getAndIncrement(); + }); + + // note: the actual order of entries in outArray is not predictable + // thus we sort before we compare results + Arrays.sort(outArray); + } + + @Test + public void test() { + testGeneratedHsail(); + } + + @Test + public void testUsingLambdaMethod() { + testGeneratedHsailUsingLambdaMethod(); + } + +} diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/lambda/AtomicIntIncAndGetTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/lambda/AtomicIntIncAndGetTest.java Mon Apr 28 11:18:15 2014 +0200 @@ -0,0 +1,69 @@ +/* + * Copyright (c) 2009, 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.hsail.test.lambda; + +import com.oracle.graal.compiler.hsail.test.infra.GraalKernelTester; +import org.junit.Test; +import java.util.concurrent.atomic.AtomicInteger; +import java.util.Arrays; + +/** + * Tests {@link AtomicInteger#incrementAndGet()}. + */ +public class AtomicIntIncAndGetTest extends GraalKernelTester { + + static final int NUM = 20; + @Result public int[] outArray = new int[NUM]; + AtomicInteger atomicInt = new AtomicInteger(); + + void setupArrays() { + for (int i = 0; i < NUM; i++) { + outArray[i] = -i; + } + } + + @Override + public void runTest() { + setupArrays(); + + dispatchLambdaKernel(NUM, (gid) -> { + outArray[gid] = atomicInt.incrementAndGet(); + }); + + // note: the actual order of entries in outArray is not predictable + // thus we sort before we compare results + Arrays.sort(outArray); + } + + @Test + public void test() { + testGeneratedHsail(); + } + + @Test + public void testUsingLambdaMethod() { + testGeneratedHsailUsingLambdaMethod(); + } + +} diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/lambda/AtomicLongAddAndGetTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/lambda/AtomicLongAddAndGetTest.java Mon Apr 28 11:18:15 2014 +0200 @@ -0,0 +1,71 @@ +/* + * Copyright (c) 2009, 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.hsail.test.lambda; + +import com.oracle.graal.compiler.hsail.test.infra.GraalKernelTester; + +import org.junit.Test; + +import java.util.concurrent.atomic.*; +import java.util.Arrays; + +/** + * Tests {@link AtomicLong#addAndGet(long)} with the delta being a constant. + */ +public class AtomicLongAddAndGetTest extends GraalKernelTester { + + static final int NUM = 20; + @Result public long[] outArray = new long[NUM]; + AtomicLong atomicLong = new AtomicLong(); + + void setupArrays() { + for (int i = 0; i < NUM; i++) { + outArray[i] = -i; + } + } + + @Override + public void runTest() { + setupArrays(); + + dispatchLambdaKernel(NUM, (gid) -> { + outArray[gid] = atomicLong.addAndGet(0x7); + }); + + // note: the actual order of entries in outArray is not predictable + // thus we sort before we compare results + Arrays.sort(outArray); + } + + @Test + public void test() { + testGeneratedHsail(); + } + + @Test + public void testUsingLambdaMethod() { + testGeneratedHsailUsingLambdaMethod(); + } + +} diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/lambda/AtomicLongGetAndAddTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/lambda/AtomicLongGetAndAddTest.java Mon Apr 28 11:18:15 2014 +0200 @@ -0,0 +1,69 @@ +/* + * Copyright (c) 2009, 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.hsail.test.lambda; + +import com.oracle.graal.compiler.hsail.test.infra.GraalKernelTester; +import org.junit.Test; +import java.util.concurrent.atomic.AtomicLong; +import java.util.Arrays; + +/** + * Tests {@link AtomicLong#getAndAdd(long)} with the delta being a constant. + */ +public class AtomicLongGetAndAddTest extends GraalKernelTester { + + static final int NUM = 20; + @Result public long[] outArray = new long[NUM]; + AtomicLong atomicLong = new AtomicLong(); + + void setupArrays() { + for (int i = 0; i < NUM; i++) { + outArray[i] = -i; + } + } + + @Override + public void runTest() { + setupArrays(); + + dispatchLambdaKernel(NUM, (gid) -> { + outArray[gid] = atomicLong.getAndAdd(0x7); + }); + + // note: the actual order of entries in outArray is not predictable + // thus we sort before we compare results + Arrays.sort(outArray); + } + + @Test + public void test() { + testGeneratedHsail(); + } + + @Test + public void testUsingLambdaMethod() { + testGeneratedHsailUsingLambdaMethod(); + } + +} diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/lambda/AtomicLongGetAndIncTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/lambda/AtomicLongGetAndIncTest.java Mon Apr 28 11:18:15 2014 +0200 @@ -0,0 +1,69 @@ +/* + * Copyright (c) 2009, 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.hsail.test.lambda; + +import com.oracle.graal.compiler.hsail.test.infra.GraalKernelTester; +import org.junit.Test; +import java.util.concurrent.atomic.AtomicLong; +import java.util.Arrays; + +/** + * Tests {@link AtomicLong#getAndIncrement()}. + */ +public class AtomicLongGetAndIncTest extends GraalKernelTester { + + static final int NUM = 20; + @Result public long[] outArray = new long[NUM]; + AtomicLong atomicLong = new AtomicLong(); + + void setupArrays() { + for (int i = 0; i < NUM; i++) { + outArray[i] = -i; + } + } + + @Override + public void runTest() { + setupArrays(); + + dispatchLambdaKernel(NUM, (gid) -> { + outArray[gid] = atomicLong.getAndIncrement(); + }); + + // note: the actual order of entries in outArray is not predictable + // thus we sort before we compare results + Arrays.sort(outArray); + } + + @Test + public void test() { + testGeneratedHsail(); + } + + @Test + public void testUsingLambdaMethod() { + testGeneratedHsailUsingLambdaMethod(); + } + +} diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/lambda/AtomicLongIncAndGetTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/lambda/AtomicLongIncAndGetTest.java Mon Apr 28 11:18:15 2014 +0200 @@ -0,0 +1,69 @@ +/* + * Copyright (c) 2009, 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.hsail.test.lambda; + +import com.oracle.graal.compiler.hsail.test.infra.GraalKernelTester; +import org.junit.Test; +import java.util.concurrent.atomic.AtomicLong; +import java.util.Arrays; + +/** + * Tests {@link AtomicLong#incrementAndGet()}. + */ +public class AtomicLongIncAndGetTest extends GraalKernelTester { + + static final int NUM = 20; + @Result public long[] outArray = new long[NUM]; + AtomicLong atomicLong = new AtomicLong(); + + void setupArrays() { + for (int i = 0; i < NUM; i++) { + outArray[i] = -i; + } + } + + @Override + public void runTest() { + setupArrays(); + + dispatchLambdaKernel(NUM, (gid) -> { + outArray[gid] = atomicLong.incrementAndGet(); + }); + + // note: the actual order of entries in outArray is not predictable + // thus we sort before we compare results + Arrays.sort(outArray); + } + + @Test + public void test() { + testGeneratedHsail(); + } + + @Test + public void testUsingLambdaMethod() { + testGeneratedHsailUsingLambdaMethod(); + } + +} diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/lambda/BigIntegerSquaredTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/lambda/BigIntegerSquaredTest.java Mon Apr 28 11:18:15 2014 +0200 @@ -0,0 +1,71 @@ +/* + * Copyright (c) 2009, 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.hsail.test.lambda; + +import com.oracle.graal.compiler.hsail.test.infra.GraalKernelTester; +import org.junit.Test; +import java.math.BigInteger; + +/** + * Tests squaring a BigInteger. + */ +public class BigIntegerSquaredTest extends GraalKernelTester { + + static final int NUM = 20; + @Result public int[] outArray = new int[NUM]; + public BigInteger[] inArray = new BigInteger[NUM]; + + void setupArrays() { + for (int i = 0; i < NUM; i++) { + inArray[i] = new BigInteger(Integer.toString(i)); + outArray[i] = -i; + } + } + + @Override + public void runTest() { + setupArrays(); + + dispatchLambdaKernel(NUM, (gid) -> { + outArray[gid] = inArray[gid].multiply(inArray[gid]).intValue(); + }); + } + + @Override + protected boolean supportsRequiredCapabilities() { + // recursive calls + return (canHandleHSAILMethodCalls()); + } + + @Test + public void test() { + testGeneratedHsail(); + } + + @Test + public void testUsingLambdaMethod() { + testGeneratedHsailUsingLambdaMethod(); + } + +} diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/lambda/Body.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/lambda/Body.java Mon Apr 28 11:18:15 2014 +0200 @@ -0,0 +1,113 @@ +/* + * Copyright (c) 2009, 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.hsail.test.lambda; + +import com.oracle.graal.compiler.hsail.test.Vec3; + +/** + * A Body object derived from Vec3 used in NBody tests. + */ +public class Body extends Vec3 { + + public Body(float _x, float _y, float _z, float _m) { + super(_x, _y, _z); + m = _m; + v = new Vec3(0, 0, 0); + } + + float m; + Vec3 v; + + public float getX() { + return x; + } + + public float getY() { + return y; + } + + public float getZ() { + return z; + } + + public float getVx() { + return v.x; + } + + public float getVy() { + return v.y; + } + + public float getVz() { + return v.z; + } + + public float getM() { + return m; + } + + public void setM(float _m) { + m = _m; + } + + public void setX(float _x) { + x = _x; + } + + public void setY(float _y) { + y = _y; + } + + public void setZ(float _z) { + z = _z; + } + + public void setVx(float _vx) { + v.x = _vx; + } + + public void setVy(float _vy) { + v.y = _vy; + } + + public void setVz(float _vz) { + v.z = _vz; + } + + @Override + public boolean equals(Object other) { + if (!(other instanceof Body)) { + return false; + } + Body oth = (Body) other; + return (oth.x == x && oth.y == y && oth.z == z && oth.m == m && v.equals(oth.v)); + } + + @Override + public int hashCode() { + // TODO Auto-generated method stub + return super.hashCode(); + } + +} diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/lambda/ByteArrayTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/lambda/ByteArrayTest.java Mon Apr 28 11:18:15 2014 +0200 @@ -0,0 +1,64 @@ +/* + * Copyright (c) 2009, 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.hsail.test.lambda; + +import com.oracle.graal.compiler.hsail.test.infra.GraalKernelTester; +import org.junit.Test; + +/** + * Tests reading from a byte array. + */ +public class ByteArrayTest extends GraalKernelTester { + + static final int NUM = 20; + @Result public int[] outArray = new int[NUM]; + public byte[] inArray = new byte[NUM]; + + void setupArrays() { + for (int i = 0; i < NUM; i++) { + inArray[i] = (byte) ((i + 1) * (i % 3 == 0 ? 1 : -1)); + outArray[i] = 99; + } + } + + @Override + public void runTest() { + setupArrays(); + + dispatchLambdaKernel(NUM, (gid) -> { + outArray[gid] = inArray[gid]; + }); + } + + @Test + public void test() { + testGeneratedHsail(); + } + + @Test + public void testUsingLambdaMethod() { + testGeneratedHsailUsingLambdaMethod(); + } + +} diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/lambda/CountMatchesBase.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/lambda/CountMatchesBase.java Mon Apr 28 11:18:15 2014 +0200 @@ -0,0 +1,47 @@ +/* + * Copyright (c) 2009, 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.hsail.test.lambda; + +import com.oracle.graal.compiler.hsail.test.infra.GraalKernelTester; + +/** + * Base class for tests that use Apache StringUtils.countMatches(). + */ +public abstract class CountMatchesBase extends GraalKernelTester { + + static final int NUM = 20; + @Result public int[] outArray = new int[NUM]; + public String[] inArray = new String[NUM]; + + void setupArrays() { + char[] chars = new char[100]; + for (int i = 0; i < chars.length; i++) { + chars[i] = (char) ('A' + (i % 10)); + } + for (int i = 0; i < NUM; i++) { + inArray[i] = new String(chars, i, 40); + } + } + +} diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/lambda/DoubleFieldAccessTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/lambda/DoubleFieldAccessTest.java Mon Apr 28 11:18:15 2014 +0200 @@ -0,0 +1,68 @@ +/* + * Copyright (c) 2009, 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.hsail.test.lambda; + +import com.oracle.graal.compiler.hsail.test.infra.GraalKernelTester; +import org.junit.Test; + +/** + * Tests accessing a double field. + */ +public class DoubleFieldAccessTest extends GraalKernelTester { + + static final int NUM = 20; + @Result public double[] outArray = new double[NUM]; + public double[] inArray = new double[NUM]; + + double doubleField = 7.0; + + void setupArrays() { + for (int i = 0; i < NUM; i++) { + inArray[i] = i; + outArray[i] = -i; + } + } + + @Override + public void runTest() { + setupArrays(); + + double[] out = outArray; + double[] in = inArray; + dispatchLambdaKernel(NUM, (gid) -> { + out[gid] = in[gid] + doubleField; + }); + } + + @Test + public void test() { + testGeneratedHsail(); + } + + @Test + public void testUsingLambdaMethod() { + testGeneratedHsailUsingLambdaMethod(); + } + +} diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/lambda/FibRecursionTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/lambda/FibRecursionTest.java Mon Apr 28 11:18:15 2014 +0200 @@ -0,0 +1,74 @@ +/* + * Copyright (c) 2009, 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.hsail.test.lambda; + +import com.oracle.graal.compiler.hsail.test.infra.GraalKernelTester; +import org.junit.Test; + +/** + * Tests a recursive method invocation. + */ +public class FibRecursionTest extends GraalKernelTester { + + static final int NUM = 20; + @Result public int[] outArray = new int[NUM]; + public int[] inArray = new int[NUM]; + + void setupArrays() { + for (int i = 0; i < NUM; i++) { + inArray[i] = i; + outArray[i] = -i; + } + } + + int fib(int n) { + return (n <= 2 ? 1 : fib(n - 2) + fib(n - 1)); + } + + @Override + public void runTest() { + setupArrays(); + + dispatchLambdaKernel(NUM, (gid) -> { + outArray[gid] = fib(inArray[gid]); + }); + } + + @Override + protected boolean supportsRequiredCapabilities() { + // recursive calls + return (canHandleHSAILMethodCalls()); + } + + @Test + public void test() { + testGeneratedHsail(); + } + + @Test + public void testUsingLambdaMethod() { + testGeneratedHsailUsingLambdaMethod(); + } + +} diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/lambda/Float2DMatrixBase.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/lambda/Float2DMatrixBase.java Mon Apr 28 11:18:15 2014 +0200 @@ -0,0 +1,51 @@ +/* + * Copyright (c) 2009, 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.hsail.test.lambda; + +import com.oracle.graal.compiler.hsail.test.infra.GraalKernelTester; + +/** + * Base class for 2D float matrix tests. + */ +public abstract class Float2DMatrixBase extends GraalKernelTester { + + float[][] matrixA; + float[][] matrixB; + @Result float[][] outMatrix; + + public void setupArrays(int range) { + matrixA = new float[range][]; + matrixB = new float[range][]; + outMatrix = new float[range][]; + for (int j = 0; j < range; j++) { + matrixA[j] = new float[range]; + matrixB[j] = new float[range]; + outMatrix[j] = new float[range]; + for (int k = 0; k < range; k++) { + matrixA[j][k] = (j + k) % 7; + matrixB[j][k] = (j + k + 1) % 8; + } + } + } +} diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/lambda/Float2DMatrixMultiplyRangeFinalTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/lambda/Float2DMatrixMultiplyRangeFinalTest.java Mon Apr 28 11:18:15 2014 +0200 @@ -0,0 +1,60 @@ +/* + * Copyright (c) 2009, 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.hsail.test.lambda; + +import org.junit.Test; + +/** + * Tests 2D float matrix multiply with range being final. + */ +public class Float2DMatrixMultiplyRangeFinalTest extends Float2DMatrixBase { + + static final int range = 6; + + @Override + public void runTest() { + setupArrays(range); + + dispatchLambdaKernel(range, (gid) -> { + for (int j = 0; j < range; j++) { + float sum = 0; + for (int k = 0; k < range; k++) { + sum += (matrixA[gid][k] * matrixB[k][j]); + } + outMatrix[gid][j] = sum; + } + }); + } + + @Test + public void test() { + testGeneratedHsail(); + } + + @Test + public void testUsingLambdaMethod() { + testGeneratedHsailUsingLambdaMethod(); + } + +} diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/lambda/Float2DMatrixMultiplySingleOutTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/lambda/Float2DMatrixMultiplySingleOutTest.java Mon Apr 28 11:18:15 2014 +0200 @@ -0,0 +1,59 @@ +/* + * Copyright (c) 2009, 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.hsail.test.lambda; + +import org.junit.Test; + +/** + * Tests 2D float matrix multiply with each workitem outputting one entry of the result matrix. + */ +public class Float2DMatrixMultiplySingleOutTest extends Float2DMatrixBase { + + @Override + public void runTest() { + int range = 20; + setupArrays(range); + + dispatchLambdaKernel(range * range, (gid) -> { + int i = gid % range; + int j = gid / range; + float sum = 0; + for (int k = 0; k < range; k++) { + sum += (matrixA[i][k] * matrixB[k][j]); + } + outMatrix[i][j] = sum; + }); + } + + @Test + public void test() { + testGeneratedHsail(); + } + + @Test + public void testUsingLambdaMethod() { + testGeneratedHsailUsingLambdaMethod(); + } + +} diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/lambda/Float2DMatrixMultiplyTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/lambda/Float2DMatrixMultiplyTest.java Mon Apr 28 11:18:15 2014 +0200 @@ -0,0 +1,59 @@ +/* + * Copyright (c) 2009, 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.hsail.test.lambda; + +import org.junit.Test; + +/** + * Tests 2D float matrix multiply with each workitem outputting one row of the result matrix. + */ +public class Float2DMatrixMultiplyTest extends Float2DMatrixBase { + + @Override + public void runTest() { + int range = 20; + setupArrays(range); + + dispatchLambdaKernel(range, (gid) -> { + for (int j = 0; j < range; j++) { + float sum = 0; + for (int k = 0; k < range; k++) { + sum += (matrixA[gid][k] * matrixB[k][j]); + } + outMatrix[gid][j] = sum; + } + }); + } + + @Test + public void test() { + testGeneratedHsail(); + } + + @Test + public void testUsingLambdaMethod() { + testGeneratedHsailUsingLambdaMethod(); + } + +} diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/lambda/FloatCondMoveTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/lambda/FloatCondMoveTest.java Mon Apr 28 11:18:15 2014 +0200 @@ -0,0 +1,64 @@ +/* + * Copyright (c) 2009, 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.hsail.test.lambda; + +import com.oracle.graal.compiler.hsail.test.infra.GraalKernelTester; +import org.junit.Test; + +/** + * Tests conditional move of a float value. + */ +public class FloatCondMoveTest extends GraalKernelTester { + + static final int NUM = 20; + @Result public float[] outArray = new float[NUM]; + public float[] inArray = new float[NUM]; + + void setupArrays() { + for (int i = 0; i < NUM; i++) { + inArray[i] = i; + outArray[i] = -i; + } + } + + @Override + public void runTest() { + setupArrays(); + + dispatchLambdaKernel(NUM, (gid) -> { + outArray[gid] = (gid > 9 ? 2.0f : 3.0f); + }); + } + + @Test + public void test() { + testGeneratedHsail(); + } + + @Test + public void testUsingLambdaMethod() { + testGeneratedHsailUsingLambdaMethod(); + } + +} diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/lambda/FloatFieldAccessTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/lambda/FloatFieldAccessTest.java Mon Apr 28 11:18:15 2014 +0200 @@ -0,0 +1,68 @@ +/* + * Copyright (c) 2009, 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.hsail.test.lambda; + +import com.oracle.graal.compiler.hsail.test.infra.GraalKernelTester; +import org.junit.Test; + +/** + * Tests accessing a float field. + */ +public class FloatFieldAccessTest extends GraalKernelTester { + + static final int NUM = 20; + @Result public float[] outArray = new float[NUM]; + public int[] inArray = new int[NUM]; + + float floatField = 7f; + + void setupArrays() { + for (int i = 0; i < NUM; i++) { + inArray[i] = i; + outArray[i] = -i; + } + } + + @Override + public void runTest() { + setupArrays(); + + float[] out = outArray; + int[] in = inArray; + dispatchLambdaKernel(NUM, (gid) -> { + out[gid] = in[gid] + floatField; + }); + } + + @Test + public void test() { + testGeneratedHsail(); + } + + @Test + public void testUsingLambdaMethod() { + testGeneratedHsailUsingLambdaMethod(); + } + +} diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/lambda/FloatFieldWriteTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/lambda/FloatFieldWriteTest.java Mon Apr 28 11:18:15 2014 +0200 @@ -0,0 +1,65 @@ +/* + * Copyright (c) 2009, 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.hsail.test.lambda; + +import com.oracle.graal.compiler.hsail.test.infra.GraalKernelTester; +import org.junit.Test; + +/** + * Tests writing a float field. + */ +public class FloatFieldWriteTest extends GraalKernelTester { + + static final int NUM = 20; + + @Result public Body[] bodyArray = new Body[NUM]; + + void setupArrays() { + for (int i = 0; i < NUM; i++) { + Body b = new Body(i, i + 1, -i, 0); + bodyArray[i] = b; + } + } + + @Override + public void runTest() { + setupArrays(); + + dispatchLambdaKernel(NUM, (gid) -> { + Body b = bodyArray[gid]; + b.z = b.x * b.y; + }); + } + + @Test + public void test() { + testGeneratedHsail(); + } + + @Test + public void testUsingLambdaMethod() { + testGeneratedHsailUsingLambdaMethod(); + } + +} diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/lambda/ForEachToGraalTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/lambda/ForEachToGraalTest.java Mon Apr 28 11:18:15 2014 +0200 @@ -0,0 +1,311 @@ +/* + * Copyright (c) 2009, 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.hsail.test.lambda; + +import java.util.stream.IntStream; + +import static org.junit.Assert.*; +import org.junit.Test; +import java.util.Arrays; +import java.util.ArrayList; + +/** + * Several tests for the Sumatra APIs. + */ +public class ForEachToGraalTest { + + // Static and instance fields to test codegen for + // each type of variable + static int staticSize = 16; + final int size = staticSize; + + static int printSize = 4; + + static int staticFactor = 3; + final int factor = staticFactor; + + class MyPoint { + + int x; + int y; + + public MyPoint(int _x, int _y) { + x = _x; + y = _y; + } + + public int getX() { + return x; + } + + public int getY() { + return y; + } + } + + public MyPoint[] buildMyPointInputArray() { + MyPoint[] inputs = new MyPoint[size]; + + for (int i = 0; i < size; i++) { + inputs[i] = new MyPoint(i, i + 1); + } + return inputs; + } + + public int[] buildIntInputArray() { + int[] inputs = new int[size]; + + for (int i = 0; i < size; i++) { + inputs[i] = i * 4; + } + return inputs; + } + + @Test + public void testForEachIntRangeNoCaptures() { + int[] dest = new int[size]; + IntStream range = IntStream.range(0, dest.length).parallel(); + + // System.out.println("testForEachIntRangeNoCaptures"); + + range.forEach(p -> { + dest[p] = p * factor; + }); + + for (int k = 0; k < dest.length; k++) { + if (k < printSize) { + // System.out.println(k + " ... " + dest[k]); + } + assertTrue(dest[k] == k * factor); + } + } + + @Test + public void testForEachIntRangeNoCapturesUseStatic() { + int[] dest = new int[size]; + IntStream range = IntStream.range(0, dest.length).parallel(); + + // System.out.println("testForEachIntRangeNoCapturesUseStatic"); + + range.forEach(p -> { + dest[p] = p * staticFactor; + }); + + for (int k = 0; k < dest.length; k++) { + if (k < printSize) { + // System.out.println(k + " ... " + dest[k]); + } + assertTrue(dest[k] == k * staticFactor); + } + } + + @Test + public void testForEachIntRangeOneCapture() { + int[] dest = new int[size]; + IntStream range = IntStream.range(0, dest.length).parallel(); + int[] data = buildIntInputArray(); + + range.forEach(p -> { + dest[p] = p * factor + data[p]; + }); + + for (int k = 0; k < dest.length; k++) { + if (k < printSize) { + // System.out.println(k + " ... " + dest[k]); + } + assertTrue(dest[k] == k * 3 + data[k]); + } + + } + + @Test + public void testForEachIntRangeOneCaptureUseStatic() { + int[] dest = new int[size]; + IntStream range = IntStream.range(0, dest.length).parallel(); + int[] data = buildIntInputArray(); + + range.forEach(p -> { + dest[p] = p * staticFactor + data[p]; + }); + + for (int k = 0; k < dest.length; k++) { + // System.out.println( k + " ... " + dest[k] ); + assertTrue(dest[k] == k * staticFactor + data[k]); + } + + } + + @Test + public void testForEachObjectStreamNoCaptures() { + MyPoint[] inputs = buildMyPointInputArray(); + + Arrays.stream(inputs).parallel().forEach(p -> { + // Swap the values + int tmp = p.x; + p.x = p.y + factor; + p.y = tmp; + }); + + for (int k = 0; k < size; k++) { + MyPoint p = inputs[k]; + // System.out.println( k + " ... p.x=" + p.x ); + assertTrue(p.x == (p.y + 1 + factor)); + } + } + + @Test + public void testForEachObjectStreamNoCapturesUseStatic() { + MyPoint[] inputs = buildMyPointInputArray(); + + Arrays.stream(inputs).parallel().forEach(p -> { + // Swap the values + int tmp = p.x; + p.x = p.y + staticFactor; + p.y = tmp; + }); + + for (int k = 0; k < size; k++) { + MyPoint p = inputs[k]; + // System.out.println( k + " ... p.x=" + p.x ); + assertTrue(p.x == (p.y + 1 + staticFactor)); + } + } + + @Test + public void testForEachObjectStreamOneCapture() { + MyPoint[] inputs = buildMyPointInputArray(); + int[] data = buildIntInputArray(); + + Arrays.stream(inputs).parallel().forEach(p -> { + p.y = data[p.x]; + }); + + for (int k = 0; k < size; k++) { + MyPoint p = inputs[k]; + // System.out.println( k + " ... p.x=" + p.x ); + assertTrue(p.y == data[p.x]); + } + + } + + @Test + public void testForEachObjectStreamOneCaptureUseStatic() { + MyPoint[] inputs = buildMyPointInputArray(); + int[] data = buildIntInputArray(); + + Arrays.stream(inputs).parallel().forEach(p -> { + p.y = data[p.x] + staticFactor; + }); + + for (int k = 0; k < size; k++) { + MyPoint p = inputs[k]; + // System.out.println( k + " ... p.x=" + p.x ); + assertTrue(p.y == (data[p.x] + +staticFactor)); + } + + } + + @Test + public void testForEachObjectStreamTwoCaptures() { + MyPoint[] inputs = buildMyPointInputArray(); + int[] data = buildIntInputArray(); + int[] data2 = buildIntInputArray(); + + Arrays.stream(inputs).parallel().forEach(p -> { + p.y = data[p.x] + data2[p.x]; + }); + + for (int k = 0; k < size; k++) { + MyPoint p = inputs[k]; + // System.out.println( k + " ... p.x=" + p.x ); + assertTrue(p.y == data[p.x] + data2[p.x]); + } + + } + + @Test + public void testForEachObjectStreamTwoCapturesUseStatic() { + MyPoint[] inputs = buildMyPointInputArray(); + int[] data = buildIntInputArray(); + int[] data2 = buildIntInputArray(); + + Arrays.stream(inputs).parallel().forEach(p -> { + p.y = data[p.x] + data2[p.x] + staticFactor; + }); + + for (int k = 0; k < size; k++) { + MyPoint p = inputs[k]; + // System.out.println( k + " ... p.x=" + p.x ); + assertTrue(p.y == data[p.x] + data2[p.x] + staticFactor); + } + + } + + // This test should fall back to the regular Java path if + // Graal throws NYI + @Test + public void testForEachIntRangeNoCapturesUseEscapingNew() { + MyPoint[] dest = new MyPoint[size]; + IntStream range = IntStream.range(0, dest.length).parallel(); + + range.forEach(p -> { + dest[p] = new MyPoint(p + p, p); + }); + + for (int k = 0; k < dest.length; k++) { + if (k < printSize) { + // System.out.println(k + " ... " + dest[k]); + } + assertTrue(dest[k].getX() == (k + k)); + } + } + + // This test should fall back to the regular Java path if + // Graal throws NYI + @Test + public void testForEachIntRangeNoCapturesUseCall() { + MyPoint[] dest = new MyPoint[size]; + ArrayList list = new ArrayList<>(size); + IntStream range = IntStream.range(0, dest.length).parallel(); + + for (int i = 0; i < dest.length; i++) { + list.add(new MyPoint(i + i, i)); + } + + range.forEach(p -> { + dest[p] = list.get(p); + }); + + for (int k = 0; k < dest.length; k++) { + if (k < printSize) { + // System.out.println(k + " ... " + dest[k]); + } + assertTrue(dest[k].getX() == (k + k)); + } + } + // public static void main(String args[]) { + // (new ForEachToGraalTest()).testForEachIntRange(); + // } + +} diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/lambda/HashMapGetTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/lambda/HashMapGetTest.java Mon Apr 28 11:18:15 2014 +0200 @@ -0,0 +1,108 @@ +/* + * Copyright (c) 2009, 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.hsail.test.lambda; + +import static com.oracle.graal.debug.Debug.*; + +import com.oracle.graal.compiler.hsail.test.infra.GraalKernelTester; +import com.oracle.graal.debug.*; + +import java.util.HashMap; + +import org.junit.Test; + +/** + * Tests calling HashMap.get(). + */ +public class HashMapGetTest extends GraalKernelTester { + + static final int NUM = 20; + + static class MyObj { + public MyObj(int id) { + this.id = id; + } + + int id; + + public int getId() { + return id; + } + + @Override + public boolean equals(Object other) { + if (!(other instanceof MyObj)) { + return false; + } + MyObj othobj = (MyObj) other; + return (othobj.id == this.id); + } + + @Override + public int hashCode() { + return 43 * (id % 7); + } + + } + + @Result public MyObj[] outArray = new MyObj[NUM]; + MyObj[] inArray = new MyObj[NUM]; + public HashMap inMap = new HashMap<>(); + + void setupArrays() { + for (int i = 0; i < NUM; i++) { + MyObj myobj = new MyObj(i); + inMap.put(myobj, new MyObj(i * 3)); + inArray[NUM - 1 - i] = myobj; + outArray[i] = null; + } + } + + @Override + public void runTest() { + setupArrays(); + + dispatchLambdaKernel(NUM, (gid) -> { + outArray[gid] = inMap.get(inArray[gid]); + }); + } + + // ForeignCall to Invoke#Direct#get + // not inlining HashMapGetTest.lambda$38@15: java.util.HashMap.get(Object):Object (20 bytes): no + // type profile exists + @Test(expected = com.oracle.graal.compiler.common.GraalInternalError.class) + public void test() { + try (DebugConfigScope s = disableIntercept()) { + testGeneratedHsail(); + } + } + + @Test(expected = com.oracle.graal.compiler.common.GraalInternalError.class) + public void testUsingLambdaMethod() { + try (DebugConfigScope s = disableIntercept()) { + testGeneratedHsailUsingLambdaMethod(); + } + } + +} diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/lambda/InstanceNBodyTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/lambda/InstanceNBodyTest.java Mon Apr 28 11:18:15 2014 +0200 @@ -0,0 +1,112 @@ +/* + * Copyright (c) 2009, 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.hsail.test.lambda; + +import java.util.*; +import org.junit.*; +import com.oracle.graal.compiler.hsail.test.infra.GraalKernelTester; + +/** + * Test intstream lambda version of nbody. + */ +public class InstanceNBodyTest extends GraalKernelTester { + + static final int bodies = 1024; + static final float delT = .005f; + static final float espSqr = 1.0f; + static final float mass = 5f; + static final int width = 768; + static final int height = 768; + + @Result float[] in_xyz = new float[bodies * 3]; // positions xy and z of bodies + + @Result float[] out_xyz = new float[bodies * 3]; // positions xy and z of bodies + + @Result float[] in_vxyz = new float[bodies * 3]; // velocity component of x,y and z of + // bodies + + @Result float[] out_vxyz = new float[bodies * 3]; + + static float[] seed_xyz = new float[bodies * 3]; + static { + final float maxDist = width / 4; + for (int body = 0; body < (bodies * 3); body += 3) { + final float theta = (float) (Math.random() * Math.PI * 2); + final float phi = (float) (Math.random() * Math.PI * 2); + final float radius = (float) (Math.random() * maxDist); + seed_xyz[body + 0] = (float) (radius * Math.cos(theta) * Math.sin(phi)) + width / 2; + seed_xyz[body + 1] = (float) (radius * Math.sin(theta) * Math.sin(phi)) + height / 2; + seed_xyz[body + 2] = (float) (radius * Math.cos(phi)); + } + } + + @Override + public void runTest() { + System.arraycopy(seed_xyz, 0, in_xyz, 0, seed_xyz.length); + Arrays.fill(out_xyz, 0f); + Arrays.fill(out_vxyz, 0f); + Arrays.fill(in_vxyz, 0f); + + // no local copies to make it an instance lambda + + dispatchLambdaKernel(bodies, (gid) -> { + final int count = bodies * 3; + final int globalId = gid * 3; + + float accx = 0.f; + float accy = 0.f; + float accz = 0.f; + for (int i = 0; i < count; i += 3) { + final float dx = in_xyz[i + 0] - in_xyz[globalId + 0]; + final float dy = in_xyz[i + 1] - in_xyz[globalId + 1]; + final float dz = in_xyz[i + 2] - in_xyz[globalId + 2]; + final float invDist = (float) (1.0 / (Math.sqrt((dx * dx) + (dy * dy) + (dz * dz) + espSqr))); + accx += mass * invDist * invDist * invDist * dx; + accy += mass * invDist * invDist * invDist * dy; + accz += mass * invDist * invDist * invDist * dz; + } + accx *= delT; + accy *= delT; + accz *= delT; + out_xyz[globalId + 0] = in_xyz[globalId + 0] + (in_vxyz[globalId + 0] * delT) + (accx * .5f * delT); + out_xyz[globalId + 1] = in_xyz[globalId + 1] + (in_vxyz[globalId + 1] * delT) + (accy * .5f * delT); + out_xyz[globalId + 2] = in_xyz[globalId + 2] + (in_vxyz[globalId + 2] * delT) + (accz * .5f * delT); + + out_vxyz[globalId + 0] = in_vxyz[globalId + 0] + accx; + out_vxyz[globalId + 1] = in_vxyz[globalId + 1] + accy; + out_vxyz[globalId + 2] = in_vxyz[globalId + 2] + accz; + }); + } + + @Test + public void test() { + testGeneratedHsail(); + } + + @Test + public void testUsingLambdaMethod() { + testGeneratedHsailUsingLambdaMethod(); + } + +} diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/lambda/InstanceOfNullTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/lambda/InstanceOfNullTest.java Mon Apr 28 11:18:15 2014 +0200 @@ -0,0 +1,59 @@ +/* + * Copyright (c) 2009, 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.hsail.test.lambda; + +import org.junit.Test; + +/** + * Tests instanceof operator on a null object. + */ +public class InstanceOfNullTest extends VirtualCallTest { + + @Override + public void runTest() { + setupArrays(); + // change some of the inShapes to null + for (int i = 0; i < NUM; i++) { + if (i % 3 == 0) + inShapeArray[i] = null; + } + + dispatchLambdaKernel(NUM, (gid) -> { + outArray[gid] = (inShapeArray[gid] instanceof Circle ? 1.0f : 2.0f); + }); + } + + @Override + @Test + public void test() { + testGeneratedHsail(); + } + + @Override + @Test + public void testUsingLambdaMethod() { + testGeneratedHsailUsingLambdaMethod(); + } + +} diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/lambda/InstanceOfTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/lambda/InstanceOfTest.java Mon Apr 28 11:18:15 2014 +0200 @@ -0,0 +1,54 @@ +/* + * Copyright (c) 2009, 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.hsail.test.lambda; + +import org.junit.Test; + +/** + * Tests instanceof operator. + */ +public class InstanceOfTest extends VirtualCallTest { + + @Override + public void runTest() { + setupArrays(); + + dispatchLambdaKernel(NUM, (gid) -> { + outArray[gid] = (inShapeArray[gid] instanceof Circle ? 1.0f : 2.0f); + }); + } + + @Override + @Test + public void test() { + testGeneratedHsail(); + } + + @Override + @Test + public void testUsingLambdaMethod() { + testGeneratedHsailUsingLambdaMethod(); + } + +} diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/lambda/InstanceOopNBodyAccTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/lambda/InstanceOopNBodyAccTest.java Mon Apr 28 11:18:15 2014 +0200 @@ -0,0 +1,125 @@ +/* + * Copyright (c) 2009, 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.hsail.test.lambda; + +import org.junit.*; +import com.oracle.graal.compiler.hsail.test.infra.GraalKernelTester; +import com.oracle.graal.compiler.hsail.test.Vec3; + +/** + * Tests Oop NBody calling a method that returns acceleration. + */ +public class InstanceOopNBodyAccTest extends GraalKernelTester { + + static final int bodies = 1024; + static final float delT = .005f; + static final float espSqr = 1.0f; + static final float mass = 5f; + static final int width = 768; + static final int height = 768; + + static class Body extends com.oracle.graal.compiler.hsail.test.lambda.Body { + + public Body(float x, float y, float z, float m) { + super(x, y, z, m); + } + + public Vec3 computeAcc(Body[] in_bodies, float espSqr1, float delT1) { + float accx = 0.f; + float accy = 0.f; + float accz = 0.f; + float myPosx = x; + float myPosy = y; + float myPosz = z; + + for (int b = 0; b < in_bodies.length; b++) { + float dx = in_bodies[b].getX() - myPosx; + float dy = in_bodies[b].getY() - myPosy; + float dz = in_bodies[b].getZ() - myPosz; + float invDist = 1.0f / (float) Math.sqrt((dx * dx) + (dy * dy) + (dz * dz) + espSqr1); + float s = in_bodies[b].getM() * invDist * invDist * invDist; + accx = accx + (s * dx); + accy = accy + (s * dy); + accz = accz + (s * dz); + } + + // now return acc as a Vec3 + return new Vec3(accx * delT1, accy * delT1, accz * delT1); + } + } + + @Result Body[] in_bodies = new Body[bodies]; + @Result Body[] out_bodies = new Body[bodies]; + + static Body[] seed_bodies = new Body[bodies]; + static { + final float maxDist = width / 4; + for (int body = 0; body < bodies; body++) { + final float theta = (float) (Math.random() * Math.PI * 2); + final float phi = (float) (Math.random() * Math.PI * 2); + final float radius = (float) (Math.random() * maxDist); + float x = (float) (radius * Math.cos(theta) * Math.sin(phi)) + width / 2; + float y = (float) (radius * Math.sin(theta) * Math.sin(phi)) + height / 2; + float z = (float) (radius * Math.cos(phi)); + seed_bodies[body] = new Body(x, y, z, mass); + } + } + + @Override + public void runTest() { + System.arraycopy(seed_bodies, 0, in_bodies, 0, seed_bodies.length); + for (int b = 0; b < bodies; b++) { + out_bodies[b] = new Body(0, 0, 0, mass); + } + // no local copies of arrays so we make it an instance lambda + + dispatchLambdaKernel(bodies, (gid) -> { + Body bin = in_bodies[gid]; + Body bout = out_bodies[gid]; + Vec3 acc = bin.computeAcc(in_bodies, espSqr, delT); + + float myPosx = bin.getX(); + float myPosy = bin.getY(); + float myPosz = bin.getZ(); + bout.setX(myPosx + (bin.getVx() * delT) + (acc.x * .5f * delT)); + bout.setY(myPosy + (bin.getVy() * delT) + (acc.y * .5f * delT)); + bout.setZ(myPosz + (bin.getVz() * delT) + (acc.z * .5f * delT)); + + bout.setVx(bin.getVx() + acc.x); + bout.setVy(bin.getVy() + acc.y); + bout.setVz(bin.getVz() + acc.z); + }); + } + + @Test + public void test() { + testGeneratedHsail(); + } + + @Test + public void testUsingLambdaMethod() { + testGeneratedHsailUsingLambdaMethod(); + } + +} diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/lambda/InstanceOopNBodyTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/lambda/InstanceOopNBodyTest.java Mon Apr 28 11:18:15 2014 +0200 @@ -0,0 +1,111 @@ +/* + * Copyright (c) 2009, 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.hsail.test.lambda; + +import org.junit.*; +import com.oracle.graal.compiler.hsail.test.infra.GraalKernelTester; + +/** + * Tests OopStream NBody as an instance lambda. + */ +public class InstanceOopNBodyTest extends GraalKernelTester { + + static final int bodies = 1024; + static final float delT = .005f; + static final float espSqr = 1.0f; + static final float mass = 5f; + static final int width = 768; + static final int height = 768; + + @Result Body[] in_bodies = new Body[bodies]; + + @Result Body[] out_bodies = new Body[bodies]; + + static Body[] seed_bodies = new Body[bodies]; + static { + final float maxDist = width / 4; + for (int body = 0; body < bodies; body++) { + final float theta = (float) (Math.random() * Math.PI * 2); + final float phi = (float) (Math.random() * Math.PI * 2); + final float radius = (float) (Math.random() * maxDist); + float x = (float) (radius * Math.cos(theta) * Math.sin(phi)) + width / 2; + float y = (float) (radius * Math.sin(theta) * Math.sin(phi)) + height / 2; + float z = (float) (radius * Math.cos(phi)); + seed_bodies[body] = new Body(x, y, z, mass); + } + } + + @Override + public void runTest() { + System.arraycopy(seed_bodies, 0, in_bodies, 0, seed_bodies.length); + for (int b = 0; b < bodies; b++) { + out_bodies[b] = new Body(0, 0, 0, mass); + } + // no local copies of arrays so we make it an instance lambda + + dispatchLambdaKernel(bodies, (gid) -> { + float accx = 0.f; + float accy = 0.f; + float accz = 0.f; + Body inb = in_bodies[gid]; + Body outb = out_bodies[gid]; + float myPosx = inb.getX(); + float myPosy = inb.getY(); + float myPosz = inb.getZ(); + + for (Body b : in_bodies) { + final float dx = b.getX() - myPosx; + final float dy = b.getY() - myPosy; + final float dz = b.getZ() - myPosz; + final float invDist = 1.0f / (float) Math.sqrt((dx * dx) + (dy * dy) + (dz * dz) + espSqr); + final float s = b.getM() * invDist * invDist * invDist; + accx = accx + (s * dx); + accy = accy + (s * dy); + accz = accz + (s * dz); + } + + accx = accx * delT; + accy = accy * delT; + accz = accz * delT; + outb.setX(myPosx + (inb.getVx() * delT) + (accx * .5f * delT)); + outb.setY(myPosy + (inb.getVy() * delT) + (accy * .5f * delT)); + outb.setZ(myPosz + (inb.getVz() * delT) + (accz * .5f * delT)); + + outb.setVx(inb.getVx() + accx); + outb.setVy(inb.getVy() + accy); + outb.setVz(inb.getVz() + accz); + }); + } + + @Test + public void test() { + testGeneratedHsail(); + } + + @Test + public void testUsingLambdaMethod() { + testGeneratedHsailUsingLambdaMethod(); + } + +} diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/lambda/IntCondMoveTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/lambda/IntCondMoveTest.java Mon Apr 28 11:18:15 2014 +0200 @@ -0,0 +1,64 @@ +/* + * Copyright (c) 2009, 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.hsail.test.lambda; + +import com.oracle.graal.compiler.hsail.test.infra.GraalKernelTester; +import org.junit.Test; + +/** + * Tests conditional move of an int value. + */ +public class IntCondMoveTest extends GraalKernelTester { + + static final int NUM = 20; + @Result public int[] outArray = new int[NUM]; + public int[] inArray = new int[NUM]; + + void setupArrays() { + for (int i = 0; i < NUM; i++) { + inArray[i] = i; + outArray[i] = -i; + } + } + + @Override + public void runTest() { + setupArrays(); + + dispatchLambdaKernel(NUM, (gid) -> { + outArray[gid] = inArray[gid] * (gid > 9 ? 2 : 3); + }); + } + + @Test + public void test() { + testGeneratedHsail(); + } + + @Test + public void testUsingLambdaMethod() { + testGeneratedHsailUsingLambdaMethod(); + } + +} diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/lambda/IntFieldAccessTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/lambda/IntFieldAccessTest.java Mon Apr 28 11:18:15 2014 +0200 @@ -0,0 +1,68 @@ +/* + * Copyright (c) 2009, 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.hsail.test.lambda; + +import com.oracle.graal.compiler.hsail.test.infra.GraalKernelTester; +import org.junit.Test; + +/** + * Tests accessing an integer field. + */ +public class IntFieldAccessTest extends GraalKernelTester { + + static final int NUM = 20; + @Result public int[] outArray = new int[NUM]; + public int[] inArray = new int[NUM]; + + int intField = 7; + + void setupArrays() { + for (int i = 0; i < NUM; i++) { + inArray[i] = i; + outArray[i] = -i; + } + } + + @Override + public void runTest() { + setupArrays(); + + int[] out = outArray; + int[] in = inArray; + dispatchLambdaKernel(NUM, (gid) -> { + out[gid] = in[gid] + intField; + }); + } + + @Test + public void test() { + testGeneratedHsail(); + } + + @Test + public void testUsingLambdaMethod() { + testGeneratedHsailUsingLambdaMethod(); + } + +} diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/lambda/IntNegateInstanceTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/lambda/IntNegateInstanceTest.java Mon Apr 28 11:18:15 2014 +0200 @@ -0,0 +1,64 @@ +/* + * Copyright (c) 2009, 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.hsail.test.lambda; + +import com.oracle.graal.compiler.hsail.test.infra.GraalKernelTester; +import org.junit.Test; + +/** + * Tests integer negation. + */ +public class IntNegateInstanceTest extends GraalKernelTester { + + static final int NUM = 20; + @Result public int[] outArray = new int[NUM]; + public int[] inArray = new int[NUM]; + + void setupArrays() { + for (int i = 0; i < NUM; i++) { + inArray[i] = i; + outArray[i] = 0; + } + } + + @Override + public void runTest() { + setupArrays(); + + dispatchLambdaKernel(NUM, (gid) -> { + outArray[gid] = -inArray[gid]; + }); + } + + @Test + public void test() { + testGeneratedHsail(); + } + + @Test + public void testUsingLambdaMethod() { + testGeneratedHsailUsingLambdaMethod(); + } + +} diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/lambda/IntSquaredInstanceTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/lambda/IntSquaredInstanceTest.java Mon Apr 28 11:18:15 2014 +0200 @@ -0,0 +1,64 @@ +/* + * Copyright (c) 2009, 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.hsail.test.lambda; + +import com.oracle.graal.compiler.hsail.test.infra.GraalKernelTester; +import org.junit.Test; + +/** + * Tests squaring an integer as an instance lambda. + */ +public class IntSquaredInstanceTest extends GraalKernelTester { + + static final int NUM = 20; + @Result public int[] outArray = new int[NUM]; + public int[] inArray = new int[NUM]; + + void setupArrays() { + for (int i = 0; i < NUM; i++) { + inArray[i] = i; + outArray[i] = -i; + } + } + + @Override + public void runTest() { + setupArrays(); + + dispatchLambdaKernel(NUM, (gid) -> { + outArray[gid] = inArray[gid] * inArray[gid] + 1; + }); + } + + @Test + public void test() { + testGeneratedHsail(); + } + + @Test + public void testUsingLambdaMethod() { + testGeneratedHsailUsingLambdaMethod(); + } + +} diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/lambda/IntSquaredStaticTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/lambda/IntSquaredStaticTest.java Mon Apr 28 11:18:15 2014 +0200 @@ -0,0 +1,61 @@ +/* + * Copyright (c) 2009, 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.hsail.test.lambda; + +import com.oracle.graal.compiler.hsail.test.infra.GraalKernelTester; +import org.junit.Test; + +/** + * Tests squaring an integer as a static lambda. + */ +public class IntSquaredStaticTest extends GraalKernelTester { + + static final int NUM = 20; + @Result public int[] outArray = new int[NUM]; + public int[] inArray = new int[NUM]; + + void setupArrays() { + for (int i = 0; i < NUM; i++) { + inArray[i] = i; + outArray[i] = -i; + } + } + + @Override + public void runTest() { + setupArrays(); + + int[] out = outArray; + int[] in = inArray; + dispatchLambdaKernel(NUM, (gid) -> { + out[gid] = in[gid] * in[gid] + 1; + }); + } + + @Test + public void test() { + testGeneratedHsail(); + } + +} diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/lambda/IntToLongTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/lambda/IntToLongTest.java Mon Apr 28 11:18:15 2014 +0200 @@ -0,0 +1,64 @@ +/* + * Copyright (c) 2009, 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.hsail.test.lambda; + +import com.oracle.graal.compiler.hsail.test.infra.GraalKernelTester; +import org.junit.Test; + +/** + * Tests conversion an int to a long. + */ +public class IntToLongTest extends GraalKernelTester { + + static final int NUM = 20; + @Result public long[] outArray = new long[NUM]; + public int[] inArray = new int[NUM]; + + void setupArrays() { + for (int i = 0; i < NUM; i++) { + inArray[i] = ((i + 1) * (i % 3 == 0 ? 1 : -1)); + outArray[i] = 99; + } + } + + @Override + public void runTest() { + setupArrays(); + + dispatchLambdaKernel(NUM, (gid) -> { + outArray[gid] = inArray[gid]; + }); + } + + @Test + public void test() { + testGeneratedHsail(); + } + + @Test + public void testUsingLambdaMethod() { + testGeneratedHsailUsingLambdaMethod(); + } + +} diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/lambda/IntegerObjectCreateTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/lambda/IntegerObjectCreateTest.java Mon Apr 28 11:18:15 2014 +0200 @@ -0,0 +1,69 @@ +/* + * Copyright (c) 2009, 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.hsail.test.lambda; + +import com.oracle.graal.compiler.hsail.test.infra.GraalKernelTester; +import org.junit.Test; + +/** + * Tests allocation of an Integer object. + */ +public class IntegerObjectCreateTest extends GraalKernelTester { + + static final int NUM = 20; + @Result public Integer[] outArray = new Integer[NUM]; + public Integer[] inArray = new Integer[NUM]; + + void setupArrays() { + for (int i = 0; i < NUM; i++) { + inArray[i] = i; + outArray[i] = -i; + } + } + + @Override + public void runTest() { + setupArrays(); + + dispatchLambdaKernel(NUM, (gid) -> { + int val = inArray[gid]; + outArray[gid] = val * val + 1; + }); + } + + @Override + protected boolean supportsRequiredCapabilities() { + return canHandleObjectAllocation(); + } + + @Test + public void test() { + testGeneratedHsail(); + } + + @Test + public void testUsingLambdaMethod() { + testGeneratedHsailUsingLambdaMethod(); + } +} diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/lambda/IntegerObjectReadTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/lambda/IntegerObjectReadTest.java Mon Apr 28 11:18:15 2014 +0200 @@ -0,0 +1,65 @@ +/* + * Copyright (c) 2009, 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.hsail.test.lambda; + +import com.oracle.graal.compiler.hsail.test.infra.GraalKernelTester; +import org.junit.Test; + +/** + * Tests reading and unboxing of an Integer object. + */ +public class IntegerObjectReadTest extends GraalKernelTester { + + static final int NUM = 20; + @Result public int[] outArray = new int[NUM]; + public Integer[] inArray = new Integer[NUM]; + + void setupArrays() { + for (int i = 0; i < NUM; i++) { + inArray[i] = i; + outArray[i] = -i; + } + } + + @Override + public void runTest() { + setupArrays(); + + dispatchLambdaKernel(NUM, (gid) -> { + int val = inArray[gid]; + outArray[gid] = val * val + 1; + }); + } + + @Test + public void test() { + testGeneratedHsail(); + } + + @Test + public void testUsingLambdaMethod() { + testGeneratedHsailUsingLambdaMethod(); + } + +} diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/lambda/LongAdderTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/lambda/LongAdderTest.java Mon Apr 28 11:18:15 2014 +0200 @@ -0,0 +1,72 @@ +/* + * Copyright (c) 2009, 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.hsail.test.lambda; + +import static com.oracle.graal.debug.Debug.*; +import static com.oracle.graal.debug.DelegatingDebugConfig.Feature.*; + +import com.oracle.graal.compiler.hsail.test.infra.GraalKernelTester; +import com.oracle.graal.debug.*; +import java.util.concurrent.atomic.LongAdder; + +import org.junit.Test; + +/** + * Tests calling LongAdder.add(). + */ +public class LongAdderTest extends GraalKernelTester { + + static final int NUM = 20; + @Result public long finalSum; + LongAdder adder = new LongAdder(); + + void setupArrays() { + } + + @Override + public void runTest() { + setupArrays(); + + dispatchLambdaKernel(NUM, (gid) -> { + adder.add(gid); + }); + + finalSum = adder.sum(); + } + + // cannot handle node: CurrentJavaThread + @Test(expected = com.oracle.graal.compiler.common.GraalInternalError.class) + public void test() { + try (DebugConfigScope dcs = setConfig(new DelegatingDebugConfig().disable(INTERCEPT))) { + testGeneratedHsail(); + } + } + + @Test(expected = com.oracle.graal.compiler.common.GraalInternalError.class) + public void testUsingLambdaMethod() { + try (DebugConfigScope dcs = setConfig(new DelegatingDebugConfig().disable(INTERCEPT))) { + testGeneratedHsailUsingLambdaMethod(); + } + } +} diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/lambda/LongCmpTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/lambda/LongCmpTest.java Mon Apr 28 11:18:15 2014 +0200 @@ -0,0 +1,68 @@ +/* + * Copyright (c) 2009, 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.hsail.test.lambda; + +import com.oracle.graal.compiler.hsail.test.infra.GraalKernelTester; +import org.junit.Test; + +/** + * Tests comparing a long to a constant. + */ +public class LongCmpTest extends GraalKernelTester { + + static final int NUM = 20; + @Result public long[] outArray = new long[NUM]; + public long[] inArray = new long[NUM]; + + void setupArrays() { + for (int i = 0; i < NUM; i++) { + inArray[i] = i; + outArray[i] = -i; + } + } + + @Override + public void runTest() { + setupArrays(); + + dispatchLambdaKernel(NUM, (gid) -> { + long val = inArray[gid]; + long result = val * val; + if (val > 9) + result++; + outArray[gid] = result; + }); + } + + @Test + public void test() { + testGeneratedHsail(); + } + + @Test + public void testUsingLambdaMethod() { + testGeneratedHsailUsingLambdaMethod(); + } + +} diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/lambda/LongCondMoveTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/lambda/LongCondMoveTest.java Mon Apr 28 11:18:15 2014 +0200 @@ -0,0 +1,64 @@ +/* + * Copyright (c) 2009, 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.hsail.test.lambda; + +import com.oracle.graal.compiler.hsail.test.infra.GraalKernelTester; +import org.junit.Test; + +/** + * Tests conditional move of a long value. + */ +public class LongCondMoveTest extends GraalKernelTester { + + static final int NUM = 20; + @Result public long[] outArray = new long[NUM]; + public long[] inArray = new long[NUM]; + + void setupArrays() { + for (int i = 0; i < NUM; i++) { + inArray[i] = i; + outArray[i] = -i; + } + } + + @Override + public void runTest() { + setupArrays(); + + dispatchLambdaKernel(NUM, (gid) -> { + outArray[gid] = inArray[gid] * (gid > 9 ? 0x123456789L : 0x123456780L); + }); + } + + @Test + public void test() { + testGeneratedHsail(); + } + + @Test + public void testUsingLambdaMethod() { + testGeneratedHsailUsingLambdaMethod(); + } + +} diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/lambda/LongNegateInstanceTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/lambda/LongNegateInstanceTest.java Mon Apr 28 11:18:15 2014 +0200 @@ -0,0 +1,64 @@ +/* + * Copyright (c) 2009, 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.hsail.test.lambda; + +import com.oracle.graal.compiler.hsail.test.infra.GraalKernelTester; +import org.junit.Test; + +/** + * Tests negation of a long. + */ +public class LongNegateInstanceTest extends GraalKernelTester { + + static final int NUM = 20; + @Result public long[] outArray = new long[NUM]; + public long[] inArray = new long[NUM]; + + void setupArrays() { + for (int i = 0; i < NUM; i++) { + inArray[i] = i; + outArray[i] = 0; + } + } + + @Override + public void runTest() { + setupArrays(); + + dispatchLambdaKernel(NUM, (gid) -> { + outArray[gid] = -inArray[gid]; + }); + } + + @Test + public void test() { + testGeneratedHsail(); + } + + @Test + public void testUsingLambdaMethod() { + testGeneratedHsailUsingLambdaMethod(); + } + +} diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/lambda/LongSquaredInstanceTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/lambda/LongSquaredInstanceTest.java Mon Apr 28 11:18:15 2014 +0200 @@ -0,0 +1,64 @@ +/* + * Copyright (c) 2009, 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.hsail.test.lambda; + +import com.oracle.graal.compiler.hsail.test.infra.GraalKernelTester; +import org.junit.Test; + +/** + * Tests squaring of a long as an instance lambda. + */ +public class LongSquaredInstanceTest extends GraalKernelTester { + + static final int NUM = 20; + @Result public long[] outArray = new long[NUM]; + public long[] inArray = new long[NUM]; + + void setupArrays() { + for (int i = 0; i < NUM; i++) { + inArray[i] = i; + outArray[i] = -i; + } + } + + @Override + public void runTest() { + setupArrays(); + + dispatchLambdaKernel(NUM, (gid) -> { + outArray[gid] = inArray[gid] * inArray[gid] + 1; + }); + } + + @Test + public void test() { + testGeneratedHsail(); + } + + @Test + public void testUsingLambdaMethod() { + testGeneratedHsailUsingLambdaMethod(); + } + +} diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/lambda/Main.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/lambda/Main.java Mon Apr 28 11:18:15 2014 +0200 @@ -0,0 +1,35 @@ +/* + * Copyright (c) 2009, 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.hsail.test.lambda; + +/** + * a place to put a direct call to a test if you don't want to go thru junit. + */ + +public class Main { + + public static void main(String[] args) { + // new StaticIntFieldAccessTest().test(); + } +} diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/lambda/MandelInstanceTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/lambda/MandelInstanceTest.java Mon Apr 28 11:18:15 2014 +0200 @@ -0,0 +1,91 @@ +/* + * Copyright (c) 2009, 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.hsail.test.lambda; + +import com.oracle.graal.compiler.hsail.test.infra.GraalKernelTester; +import org.junit.Test; + +/** + * Tests mandel as an instance lambda. + */ + +public class MandelInstanceTest extends GraalKernelTester { + + static final int WIDTH = 768; + static final int HEIGHT = WIDTH; + static final int maxIterations = 64; + + static final int RANGE = WIDTH * HEIGHT; + @Result public int[] rgb = new int[RANGE]; + int[] palette = new int[256]; + + void setupPalette(int[] in) { + for (int i = 0; i < in.length; i++) { + in[i] = i; + } + } + + @Override + public void runTest() { + setupPalette(palette); + + float x_offset = -1f; + float y_offset = 0f; + float scale = 3f; + + // call it for a range, specifying the lambda + dispatchLambdaKernel(RANGE, (gid) -> { + final int width = WIDTH; + final int height = HEIGHT; + float lx = (((gid % width * scale) - ((scale / 2) * width)) / width) + x_offset; + float ly = (((gid / width * scale) - ((scale / 2) * height)) / height) + y_offset; + + int count = 0; + float zx = lx; + float zy = ly; + float new_zx = 0f; + + // Iterate until the algorithm converges or until maxIterations are reached. + while (count < maxIterations && zx * zx + zy * zy < 8) { + new_zx = zx * zx - zy * zy + lx; + zy = 2 * zx * zy + ly; + zx = new_zx; + count++; + } + + rgb[gid] = palette[count]; + }); + } + + @Test + public void test() { + testGeneratedHsail(); + } + + @Test + public void testUsingLambdaMethod() { + testGeneratedHsailUsingLambdaMethod(); + } + +} diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/lambda/MandelStaticTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/lambda/MandelStaticTest.java Mon Apr 28 11:18:15 2014 +0200 @@ -0,0 +1,93 @@ +/* + * Copyright (c) 2009, 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.hsail.test.lambda; + +import com.oracle.graal.compiler.hsail.test.infra.GraalKernelTester; +import org.junit.Test; + +/** + * Tests static lambda version of Mandel. + */ +public class MandelStaticTest extends GraalKernelTester { + + static final int WIDTH = 768; + static final int HEIGHT = WIDTH; + static final int maxIterations = 64; + + static final int RANGE = WIDTH * HEIGHT; + @Result public int[] rgb = new int[RANGE]; + + void setupPalette(int[] in) { + for (int i = 0; i < in.length; i++) { + in[i] = i; + } + } + + @Override + public void runTest() { + int[] palette = new int[256]; + setupPalette(palette); + + // since we want this to be a fully static lambda, make local copies + // of the arrays and values that will get captured by the lambda + int[] rgb1 = this.rgb; + float x_offset = -1f; + float y_offset = 0f; + float scale = 3f; + + // call it for a range, specifying lambda + dispatchLambdaKernel(RANGE, (gid) -> { + final int width = WIDTH; + final int height = HEIGHT; + float lx = (((gid % width * scale) - ((scale / 2) * width)) / width) + x_offset; + float ly = (((gid / width * scale) - ((scale / 2) * height)) / height) + y_offset; + + int count = 0; + float zx = lx; + float zy = ly; + float new_zx = 0f; + + // Iterate until the algorithm converges or until maxIterations are reached. + while (count < maxIterations && zx * zx + zy * zy < 8) { + new_zx = zx * zx - zy * zy + lx; + zy = 2 * zx * zy + ly; + zx = new_zx; + count++; + } + + rgb1[gid] = palette[count]; + }); + } + + @Test + public void test() { + testGeneratedHsail(); + } + + @Test + public void testUsingLambdaMethod() { + testGeneratedHsailUsingLambdaMethod(); + } + +} diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/lambda/NewStringEqualsTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/lambda/NewStringEqualsTest.java Mon Apr 28 11:18:15 2014 +0200 @@ -0,0 +1,81 @@ +/* + * Copyright (c) 2009, 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.hsail.test.lambda; + +import static com.oracle.graal.debug.Debug.*; + +import com.oracle.graal.compiler.hsail.test.infra.GraalKernelTester; +import com.oracle.graal.debug.*; + +import org.junit.Test; + +/** + * Tests creating a String and calling .equals() on it. + */ +public class NewStringEqualsTest extends GraalKernelTester { + + static final int NUM = 20; + @Result public boolean[] outArray = new boolean[NUM]; + char[] chars = new char[100]; + + void setupArrays() { + for (int i = 0; i < chars.length; i++) { + chars[i] = (char) ('A' + i); + } + for (int i = 0; i < NUM; i++) { + } + } + + @Override + public void runTest() { + setupArrays(); + String base = "ABCDEFGHIJ"; + + dispatchLambdaKernel(NUM, (gid) -> { + outArray[gid] = new String(chars, 0, 10 + (gid % 3)).equals(base); + }); + } + + @Override + protected boolean supportsRequiredCapabilities() { + // although not escaping, seems to require object allocation support + return (canHandleObjectAllocation()); + } + + // NYI emitForeignCall charAlignedDisjointArraycopy + @Test(expected = com.oracle.graal.compiler.common.GraalInternalError.class) + public void test() { + try (DebugConfigScope s = disableIntercept()) { + testGeneratedHsail(); + } + } + + @Test(expected = com.oracle.graal.compiler.common.GraalInternalError.class) + public void testUsingLambdaMethod() { + try (DebugConfigScope s = disableIntercept()) { + testGeneratedHsailUsingLambdaMethod(); + } + } + +} diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/lambda/NewStringLenTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/lambda/NewStringLenTest.java Mon Apr 28 11:18:15 2014 +0200 @@ -0,0 +1,74 @@ +/* + * Copyright (c) 2009, 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.hsail.test.lambda; + +import com.oracle.graal.compiler.hsail.test.infra.GraalKernelTester; +import org.junit.Test; + +/** + * Tests creating a String and calling .length() on it. + */ +public class NewStringLenTest extends GraalKernelTester { + + static final int NUM = 20; + @Result public int[] outArray = new int[NUM]; + public int[] inArray = new int[NUM]; + char[] chars = new char[100]; + + void setupArrays() { + for (int i = 0; i < chars.length; i++) { + chars[i] = 'A'; + } + for (int i = 0; i < NUM; i++) { + inArray[i] = i + 10; + outArray[i] = -i; + } + } + + @Override + public void runTest() { + setupArrays(); + + dispatchLambdaKernel(NUM, (gid) -> { + outArray[gid] = Integer.toString(gid).length(); + }); + } + + @Override + protected boolean supportsRequiredCapabilities() { + // although not escaping, seems to require object allocation support + return (canHandleObjectAllocation()); + } + + @Test + public void test() { + testGeneratedHsail(); + } + + @Test + public void testUsingLambdaMethod() { + testGeneratedHsailUsingLambdaMethod(); + } + +} diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/lambda/NonEscapingNewArrayTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/lambda/NonEscapingNewArrayTest.java Mon Apr 28 11:18:15 2014 +0200 @@ -0,0 +1,63 @@ +/* + * Copyright (c) 2009, 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.hsail.test.lambda; + +import com.oracle.graal.compiler.hsail.test.infra.GraalKernelTester; +import org.junit.Test; + +/** + * Tests creating a non-escaping array and using it. + */ +public class NonEscapingNewArrayTest extends GraalKernelTester { + + static final int NUM = 20; + @Result public float[] outArray = new float[NUM]; + + void setupArrays() { + for (int i = 0; i < NUM; i++) { + outArray[i] = -i; + } + } + + @Override + public void runTest() { + setupArrays(); + + dispatchLambdaKernel(NUM, (gid) -> { + float[] ary = {gid, gid + 1, gid + 2}; + outArray[gid] = ary[0] * ary[1] * ary[2]; + }); + } + + @Test + public void test() { + testGeneratedHsail(); + } + + @Test + public void testUsingLambdaMethod() { + testGeneratedHsailUsingLambdaMethod(); + } + +} diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/lambda/NonEscapingNewObjWithArrayTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/lambda/NonEscapingNewObjWithArrayTest.java Mon Apr 28 11:18:15 2014 +0200 @@ -0,0 +1,95 @@ +/* + * Copyright (c) 2009, 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.hsail.test.lambda; + +import static com.oracle.graal.debug.Debug.*; +import static com.oracle.graal.debug.DelegatingDebugConfig.Feature.*; + +import com.oracle.graal.compiler.hsail.test.infra.GraalKernelTester; +import com.oracle.graal.debug.*; + +import org.junit.Test; + +import java.util.Arrays; + +/** + * Tests non-escaping object creation and calling a method on it. + */ +public class NonEscapingNewObjWithArrayTest extends GraalKernelTester { + static final int NUM = 20; + @Result public float[] outArray = new float[NUM]; + + static class MyObj { + float a[]; + + public MyObj(float[] src, int ofst) { + a = Arrays.copyOfRange(src, ofst, ofst + 3); + } + + public float productOf() { + return a[0] * a[1] * a[2]; + } + } + + void setupArrays() { + for (int i = 0; i < NUM; i++) { + outArray[i] = -i; + } + } + + @Override + public void runTest() { + setupArrays(); + float[] fsrc = new float[2 * NUM]; + for (int i = 0; i < 2 * NUM; i++) { + fsrc[i] = i; + } + + dispatchLambdaKernel(NUM, (gid) -> { + outArray[gid] = new MyObj(fsrc, gid).productOf(); + }); + } + + @Override + protected boolean supportsRequiredCapabilities() { + // although not escaping, seems to require object allocation support + return (canHandleObjectAllocation()); + } + + // NYI emitForeignCall floatArraycopy + @Test(expected = com.oracle.graal.compiler.common.GraalInternalError.class) + public void test() { + try (DebugConfigScope s = disableIntercept()) { + testGeneratedHsail(); + } + } + + @Test(expected = com.oracle.graal.compiler.common.GraalInternalError.class) + public void testUsingLambdaMethod() { + try (DebugConfigScope dcs = setConfig(new DelegatingDebugConfig().disable(INTERCEPT))) { + testGeneratedHsailUsingLambdaMethod(); + } + } + +} diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/lambda/NonEscapingNewTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/lambda/NonEscapingNewTest.java Mon Apr 28 11:18:15 2014 +0200 @@ -0,0 +1,68 @@ +/* + * Copyright (c) 2009, 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.hsail.test.lambda; + +import com.oracle.graal.compiler.hsail.test.infra.GraalKernelTester; +import org.junit.Test; +import com.oracle.graal.compiler.hsail.test.Vec3; + +/** + * Tests creation of three non-escaping objects. + */ +public class NonEscapingNewTest extends GraalKernelTester { + + static final int NUM = 20; + @Result public float[] outArray = new float[NUM]; + public Vec3[] inArray = new Vec3[NUM]; + + void setupArrays() { + for (int i = 0; i < NUM; i++) { + inArray[i] = new Vec3(i, i + 1, i + 2); + outArray[i] = -i; + } + } + + @Override + public void runTest() { + setupArrays(); + + dispatchLambdaKernel(NUM, (gid) -> { + Vec3 veca = inArray[gid]; + Vec3 vecb = inArray[(gid + 1) % NUM]; + Vec3 vecresult = Vec3.add(veca, vecb); + outArray[gid] = vecresult.z; + }); + } + + @Test + public void test() { + testGeneratedHsail(); + } + + @Test + public void testUsingLambdaMethod() { + testGeneratedHsailUsingLambdaMethod(); + } + +} diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/lambda/ObjectArrayInstanceDerivedTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/lambda/ObjectArrayInstanceDerivedTest.java Mon Apr 28 11:18:15 2014 +0200 @@ -0,0 +1,86 @@ +/* + * Copyright (c) 2009, 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.hsail.test.lambda; + +import org.junit.*; + +import com.oracle.graal.compiler.hsail.test.infra.GraalKernelTester; + +/** + * Tests calling a method on an object when there are derived types of that object. Note: if you + * enable these tests, not only will these tests fail but other tests like ObjectArrayInstanceTest + * will also fail because they depend on there being no derived classes from Body. + */ +public class ObjectArrayInstanceDerivedTest extends GraalKernelTester { + + static final int NUM = 20; + + class DerivedBody extends Body { + + DerivedBody(float x, float y, float z, float m) { + super(x, y, z, m); + } + + @Override + public float getX() { + return 42.0f; + } + } + + @Result public float[] outArray = new float[NUM]; + public Body[] inBodyArray = new Body[NUM]; + public Body[] unusedBodyArray = new Body[NUM]; + public DerivedBody[] unusedDerivedBodyArray = new DerivedBody[NUM]; + + void setupArrays() { + for (int i = 0; i < NUM; i++) { + inBodyArray[i] = new Body(i, i + 1, i + 2, i + 3); + // unusedBodyArray[i] = new DerivedBody(i, i+1, i+2, i+3); + outArray[i] = -i; + } + } + + @Override + public void runTest() { + setupArrays(); + + dispatchLambdaKernel(NUM, (gid) -> { + Body b = inBodyArray[gid]; + outArray[gid] = b.getX() * b.getY(); + }); + } + + @Ignore + @Test + public void test() { + testGeneratedHsail(); + } + + @Ignore + @Test + public void testUsingLambdaMethod() { + testGeneratedHsailUsingLambdaMethod(); + } + +} diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/lambda/ObjectArrayInstanceTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/lambda/ObjectArrayInstanceTest.java Mon Apr 28 11:18:15 2014 +0200 @@ -0,0 +1,69 @@ +/* + * Copyright (c) 2009, 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.hsail.test.lambda; + +import com.oracle.graal.compiler.hsail.test.infra.GraalKernelTester; + +import org.junit.*; + +/** + * Tests calling a method on an object when there are no derived types of that object. + */ +public class ObjectArrayInstanceTest extends GraalKernelTester { + + static final int NUM = 20; + + @Result public float[] outArray = new float[NUM]; + public Body[] inBodyArray = new Body[NUM]; + + void setupArrays() { + for (int i = 0; i < NUM; i++) { + inBodyArray[i] = new Body(i, i + 1, i + 2, i + 3); + outArray[i] = -i; + } + } + + @Override + public void runTest() { + setupArrays(); + + dispatchLambdaKernel(NUM, (gid) -> { + Body b = inBodyArray[gid]; + outArray[gid] = b.getX() * b.getY(); + }); + } + + @Ignore + @Test + public void test() { + testGeneratedHsail(); + } + + @Ignore + @Test + public void testUsingLambdaMethod() { + testGeneratedHsailUsingLambdaMethod(); + } + +} diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/lambda/ObjectStoreNullTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/lambda/ObjectStoreNullTest.java Mon Apr 28 11:18:15 2014 +0200 @@ -0,0 +1,54 @@ +/* + * Copyright (c) 2009, 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.hsail.test.lambda; + +import org.junit.Test; + +/** + * Tests the storing of null in an Object array + */ +public class ObjectStoreNullTest extends ObjectStoreTest { + + @Override + public void runTest() { + setupArrays(); + + dispatchLambdaKernel(NUM, (gid) -> { + outBodyArray[gid] = (gid % 3 == 1 ? null : inBodyArray[gid]); + }); + } + + @Override + @Test + public void test() { + testGeneratedHsail(); + } + + @Override + @Test + public void testUsingLambdaMethod() { + testGeneratedHsailUsingLambdaMethod(); + } + +} diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/lambda/ObjectStoreTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/lambda/ObjectStoreTest.java Mon Apr 28 11:18:15 2014 +0200 @@ -0,0 +1,65 @@ +/* + * Copyright (c) 2009, 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.hsail.test.lambda; + +import com.oracle.graal.compiler.hsail.test.infra.GraalKernelTester; +import org.junit.Test; + +/** + * Tests copying an object from one array to another. + */ +public class ObjectStoreTest extends GraalKernelTester { + + static final int NUM = 20; + + @Result public Body[] outBodyArray = new Body[NUM]; + public Body[] inBodyArray = new Body[NUM]; + + void setupArrays() { + for (int i = 0; i < NUM; i++) { + inBodyArray[i] = new Body(i, i + 1, i + 2, i + 3); + outBodyArray[i] = null; + } + } + + @Override + public void runTest() { + setupArrays(); + + dispatchLambdaKernel(NUM, (gid) -> { + outBodyArray[gid] = inBodyArray[gid]; + }); + } + + @Test + public void test() { + testGeneratedHsail(); + } + + @Test + public void testUsingLambdaMethod() { + testGeneratedHsailUsingLambdaMethod(); + } + +} diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/lambda/OverloadMethodTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/lambda/OverloadMethodTest.java Mon Apr 28 11:18:15 2014 +0200 @@ -0,0 +1,72 @@ +/* + * Copyright (c) 2009, 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.hsail.test.lambda; + +import com.oracle.graal.compiler.hsail.test.infra.GraalKernelTester; +import org.junit.Test; + +/** + * Tests calling methods with the same name but different signatures. + */ +public class OverloadMethodTest extends GraalKernelTester { + + static final int NUM = 20; + @Result public int[] outArray = new int[NUM]; + public int[] inArray = new int[NUM]; + + void setupArrays() { + for (int i = 0; i < NUM; i++) { + inArray[i] = i; + outArray[i] = -i; + } + } + + int addArgs(int a, int b) { + return a + b; + } + + int addArgs(int a, int b, int c) { + return a + b + c; + } + + @Override + public void runTest() { + setupArrays(); + + dispatchLambdaKernel(NUM, (gid) -> { + outArray[gid] = (gid > 9 ? addArgs(inArray[gid], gid + 1) : addArgs(inArray[gid], gid - 1, gid - 2)); + }); + } + + @Test + public void test() { + testGeneratedHsail(); + } + + @Test + public void testUsingLambdaMethod() { + testGeneratedHsailUsingLambdaMethod(); + } + +} diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/lambda/ShortArrayTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/lambda/ShortArrayTest.java Mon Apr 28 11:18:15 2014 +0200 @@ -0,0 +1,64 @@ +/* + * Copyright (c) 2009, 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.hsail.test.lambda; + +import com.oracle.graal.compiler.hsail.test.infra.GraalKernelTester; +import org.junit.Test; + +/** + * Tests accessing an array of shorts. + */ +public class ShortArrayTest extends GraalKernelTester { + + static final int NUM = 20; + @Result public int[] outArray = new int[NUM]; + public short[] inArray = new short[NUM]; + + void setupArrays() { + for (int i = 0; i < NUM; i++) { + inArray[i] = (short) ((i + 1) * (i % 3 == 0 ? 1 : -1)); + outArray[i] = 99; + } + } + + @Override + public void runTest() { + setupArrays(); + + dispatchLambdaKernel(NUM, (gid) -> { + outArray[gid] = inArray[gid]; + }); + } + + @Test + public void test() { + testGeneratedHsail(); + } + + @Test + public void testUsingLambdaMethod() { + testGeneratedHsailUsingLambdaMethod(); + } + +} diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/lambda/StaticFloatFieldReadTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/lambda/StaticFloatFieldReadTest.java Mon Apr 28 11:18:15 2014 +0200 @@ -0,0 +1,68 @@ +/* + * Copyright (c) 2009, 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.hsail.test.lambda; + +import com.oracle.graal.compiler.hsail.test.infra.GraalKernelTester; +import org.junit.Test; + +/** + * Tests reading from a static float field. + */ +public class StaticFloatFieldReadTest extends GraalKernelTester { + + static final int NUM = 20; + @Result public float[] outArray = new float[NUM]; + public float[] inArray = new float[NUM]; + + static float floatField = 7.123f; + + void setupArrays() { + for (int i = 0; i < NUM; i++) { + inArray[i] = i; + outArray[i] = -i; + } + } + + @Override + public void runTest() { + setupArrays(); + + float[] out = outArray; + float[] in = inArray; + dispatchLambdaKernel(NUM, (gid) -> { + out[gid] = in[gid] + floatField; + }); + } + + @Test + public void test() { + testGeneratedHsail(); + } + + @Test + public void testUsingLambdaMethod() { + testGeneratedHsailUsingLambdaMethod(); + } + +} diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/lambda/StaticIntField2ReadTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/lambda/StaticIntField2ReadTest.java Mon Apr 28 11:18:15 2014 +0200 @@ -0,0 +1,56 @@ +/* + * Copyright (c) 2009, 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.hsail.test.lambda; + +import org.junit.Test; + +/** + * Tests reading from a two static int fields in different classes. + */ +public class StaticIntField2ReadTest extends StaticIntFieldReadTest { + + static int intField2 = 8; + + @Override + public void runTest() { + setupArrays(); + + dispatchLambdaKernel(NUM, (gid) -> { + outArray[gid] = inArray[gid] * intField1 + intField2; + }); + } + + @Override + @Test + public void test() { + testGeneratedHsail(); + } + + @Override + @Test + public void testUsingLambdaMethod() { + testGeneratedHsailUsingLambdaMethod(); + } + +} diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/lambda/StaticIntFieldReadTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/lambda/StaticIntFieldReadTest.java Mon Apr 28 11:18:15 2014 +0200 @@ -0,0 +1,66 @@ +/* + * Copyright (c) 2009, 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.hsail.test.lambda; + +import com.oracle.graal.compiler.hsail.test.infra.GraalKernelTester; +import org.junit.Test; + +/** + * Tests reading from a static int field. + */ +public class StaticIntFieldReadTest extends GraalKernelTester { + + static final int NUM = 20; + @Result public int[] outArray = new int[NUM]; + public int[] inArray = new int[NUM]; + + static int intField1 = 7; + + void setupArrays() { + for (int i = 0; i < NUM; i++) { + inArray[i] = i; + outArray[i] = -i; + } + } + + @Override + public void runTest() { + setupArrays(); + + dispatchLambdaKernel(NUM, (gid) -> { + outArray[gid] = inArray[gid] + intField1; + }); + } + + @Test + public void test() { + testGeneratedHsail(); + } + + @Test + public void testUsingLambdaMethod() { + testGeneratedHsailUsingLambdaMethod(); + } + +} diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/lambda/StaticIntFieldSameClassTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/lambda/StaticIntFieldSameClassTest.java Mon Apr 28 11:18:15 2014 +0200 @@ -0,0 +1,62 @@ +/* + * Copyright (c) 2009, 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.hsail.test.lambda; + +import org.junit.Test; + +/** + * Tests reading from a two static int fields in the same class. + */ +public class StaticIntFieldSameClassTest extends StaticIntFieldReadTest { + + static int myField1 = 5; + static int myField2 = -99; + @Result int fieldResult; + + @Override + public void runTest() { + setupArrays(); + myField2 = -99; + dispatchLambdaKernel(NUM, (gid) -> { + int val = inArray[gid] * myField1; + outArray[gid] = val; + if (gid == 3) + myField2 = val + gid; + }); + fieldResult = myField2; + } + + @Override + @Test + public void test() { + testGeneratedHsail(); + } + + @Override + @Test + public void testUsingLambdaMethod() { + testGeneratedHsailUsingLambdaMethod(); + } + +} diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/lambda/StaticIntFieldWriteTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/lambda/StaticIntFieldWriteTest.java Mon Apr 28 11:18:15 2014 +0200 @@ -0,0 +1,70 @@ +/* + * Copyright (c) 2009, 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.hsail.test.lambda; + +import com.oracle.graal.compiler.hsail.test.infra.GraalKernelTester; +import org.junit.Test; + +/** + * Tests writing a static int field. + */ +public class StaticIntFieldWriteTest extends GraalKernelTester { + + static final int NUM = 20; + @Result public int[] outArray = new int[NUM]; + public int[] inArray = new int[NUM]; + @Result int fieldResult; + + static int intStaticField = -99; + + void setupArrays() { + for (int i = 0; i < NUM; i++) { + inArray[i] = i; + outArray[i] = -i; + } + } + + @Override + public void runTest() { + setupArrays(); + intStaticField = -99; + dispatchLambdaKernel(NUM, (gid) -> { + outArray[gid] = inArray[gid] * 2; + if (gid == 3) + intStaticField = outArray[gid]; + }); + fieldResult = intStaticField; // save for kerneltester comparison + } + + @Test + public void test() { + testGeneratedHsail(); + } + + @Test + public void testUsingLambdaMethod() { + testGeneratedHsailUsingLambdaMethod(); + } + +} diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/lambda/StaticNBodyTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/lambda/StaticNBodyTest.java Mon Apr 28 11:18:15 2014 +0200 @@ -0,0 +1,116 @@ +/* + * Copyright (c) 2009, 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.hsail.test.lambda; + +import java.util.*; +import org.junit.*; +import com.oracle.graal.compiler.hsail.test.infra.GraalKernelTester; + +/** + * Tests a static lambda version of nbody. + */ +public class StaticNBodyTest extends GraalKernelTester { + + static final int bodies = 1024; + static final float delT = .005f; + static final float espSqr = 1.0f; + static final float mass = 5f; + static final int width = 768; + static final int height = 768; + + @Result float[] in_xyz = new float[bodies * 3]; // positions xy and z of bodies + + @Result float[] out_xyz = new float[bodies * 3]; // positions xy and z of bodies + + @Result float[] in_vxyz = new float[bodies * 3]; // velocity component of x,y and z of + // bodies + + @Result float[] out_vxyz = new float[bodies * 3]; + + static float[] seed_xyz = new float[bodies * 3]; + static { + final float maxDist = width / 4; + for (int body = 0; body < (bodies * 3); body += 3) { + final float theta = (float) (Math.random() * Math.PI * 2); + final float phi = (float) (Math.random() * Math.PI * 2); + final float radius = (float) (Math.random() * maxDist); + seed_xyz[body + 0] = (float) (radius * Math.cos(theta) * Math.sin(phi)) + width / 2; + seed_xyz[body + 1] = (float) (radius * Math.sin(theta) * Math.sin(phi)) + height / 2; + seed_xyz[body + 2] = (float) (radius * Math.cos(phi)); + } + } + + @Override + public void runTest() { + System.arraycopy(seed_xyz, 0, in_xyz, 0, seed_xyz.length); + Arrays.fill(out_xyz, 0f); + Arrays.fill(out_vxyz, 0f); + Arrays.fill(in_vxyz, 0f); + + // local copies for a static lambda + float[] in_xyz1 = this.in_xyz; + float[] out_xyz1 = this.out_xyz; + float[] in_vxyz1 = this.in_vxyz; + float[] out_vxyz1 = this.out_vxyz; + + dispatchLambdaKernel(bodies, (gid) -> { + final int count = bodies * 3; + final int globalId = gid * 3; + + float accx = 0.f; + float accy = 0.f; + float accz = 0.f; + for (int i = 0; i < count; i += 3) { + final float dx = in_xyz1[i + 0] - in_xyz1[globalId + 0]; + final float dy = in_xyz1[i + 1] - in_xyz1[globalId + 1]; + final float dz = in_xyz1[i + 2] - in_xyz1[globalId + 2]; + final float invDist = (float) (1.0 / (Math.sqrt((dx * dx) + (dy * dy) + (dz * dz) + espSqr))); + accx += mass * invDist * invDist * invDist * dx; + accy += mass * invDist * invDist * invDist * dy; + accz += mass * invDist * invDist * invDist * dz; + } + accx *= delT; + accy *= delT; + accz *= delT; + out_xyz1[globalId + 0] = in_xyz1[globalId + 0] + (in_vxyz1[globalId + 0] * delT) + (accx * .5f * delT); + out_xyz1[globalId + 1] = in_xyz1[globalId + 1] + (in_vxyz1[globalId + 1] * delT) + (accy * .5f * delT); + out_xyz1[globalId + 2] = in_xyz1[globalId + 2] + (in_vxyz1[globalId + 2] * delT) + (accz * .5f * delT); + + out_vxyz1[globalId + 0] = in_vxyz1[globalId + 0] + accx; + out_vxyz1[globalId + 1] = in_vxyz1[globalId + 1] + accy; + out_vxyz1[globalId + 2] = in_vxyz1[globalId + 2] + accz; + }); + } + + @Test + public void test() { + testGeneratedHsail(); + } + + @Test + public void testUsingLambdaMethod() { + testGeneratedHsailUsingLambdaMethod(); + } + +} diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/lambda/StringContainsTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/lambda/StringContainsTest.java Mon Apr 28 11:18:15 2014 +0200 @@ -0,0 +1,68 @@ +/* + * Copyright (c) 2009, 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.hsail.test.lambda; + +import com.oracle.graal.compiler.hsail.test.infra.GraalKernelTester; +import org.junit.Test; + +/** + * Tests calling String.contains(). + */ +public class StringContainsTest extends GraalKernelTester { + + static final int NUM = 20; + @Result public boolean[] outArray = new boolean[NUM]; + public String[] inArray = new String[NUM]; + + void setupArrays() { + char[] chars = new char[100]; + for (int i = 0; i < chars.length; i++) { + chars[i] = (char) ('A' + i); + } + for (int i = 0; i < NUM; i++) { + inArray[i] = new String(chars, i, 10); + } + } + + @Override + public void runTest() { + setupArrays(); + String base = "CDE"; + + dispatchLambdaKernel(NUM, (gid) -> { + outArray[gid] = inArray[gid].contains(base); + }); + } + + @Test + public void test() { + testGeneratedHsail(); + } + + @Test + public void testUsingLambdaMethod() { + testGeneratedHsailUsingLambdaMethod(); + } + +} diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/lambda/StringEqualsTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/lambda/StringEqualsTest.java Mon Apr 28 11:18:15 2014 +0200 @@ -0,0 +1,68 @@ +/* + * Copyright (c) 2009, 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.hsail.test.lambda; + +import com.oracle.graal.compiler.hsail.test.infra.GraalKernelTester; +import org.junit.Test; + +/** + * Tests calling String.equals(). + */ +public class StringEqualsTest extends GraalKernelTester { + + static final int NUM = 20; + @Result public boolean[] outArray = new boolean[NUM]; + public String[] inArray = new String[NUM]; + + void setupArrays() { + char[] chars = new char[100]; + for (int i = 0; i < chars.length; i++) { + chars[i] = (char) ('A' + i); + } + for (int i = 0; i < NUM; i++) { + inArray[i] = new String(chars, 0, 10 + (i % 3)); + } + } + + @Override + public void runTest() { + setupArrays(); + String base = "ABCDEFGHIJ"; + + dispatchLambdaKernel(NUM, (gid) -> { + outArray[gid] = inArray[gid].equals(base); + }); + } + + @Test + public void test() { + testGeneratedHsail(); + } + + @Test + public void testUsingLambdaMethod() { + testGeneratedHsailUsingLambdaMethod(); + } + +} diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/lambda/StringHashTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/lambda/StringHashTest.java Mon Apr 28 11:18:15 2014 +0200 @@ -0,0 +1,68 @@ +/* + * Copyright (c) 2009, 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.hsail.test.lambda; + +import com.oracle.graal.compiler.hsail.test.infra.GraalKernelTester; +import org.junit.Test; + +/** + * Tests calling String.hashCode(). + */ +public class StringHashTest extends GraalKernelTester { + + static final int NUM = 20; + @Result public int[] outArray = new int[NUM]; + public String[] inArray = new String[NUM]; + + void setupArrays() { + char[] chars = new char[100]; + for (int i = 0; i < chars.length; i++) { + chars[i] = (char) ('A' + i); + } + for (int i = 0; i < NUM; i++) { + inArray[i] = new String(chars, 0, i + 1); + outArray[i] = -i; + } + } + + @Override + public void runTest() { + setupArrays(); + + dispatchLambdaKernel(NUM, (gid) -> { + outArray[gid] = inArray[gid].hashCode(); + }); + } + + @Test + public void test() { + testGeneratedHsail(); + } + + @Test + public void testUsingLambdaMethod() { + testGeneratedHsailUsingLambdaMethod(); + } + +} diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/lambda/StringLenTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/lambda/StringLenTest.java Mon Apr 28 11:18:15 2014 +0200 @@ -0,0 +1,68 @@ +/* + * Copyright (c) 2009, 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.hsail.test.lambda; + +import com.oracle.graal.compiler.hsail.test.infra.GraalKernelTester; +import org.junit.Test; + +/** + * Tests calling String.length(). + */ +public class StringLenTest extends GraalKernelTester { + + static final int NUM = 20; + @Result public int[] outArray = new int[NUM]; + public String[] inArray = new String[NUM]; + + void setupArrays() { + char[] chars = new char[100]; + for (int i = 0; i < chars.length; i++) { + chars[i] = 'A'; + } + for (int i = 0; i < NUM; i++) { + inArray[i] = new String(chars, 0, i + 10); + outArray[i] = -i; + } + } + + @Override + public void runTest() { + setupArrays(); + + dispatchLambdaKernel(NUM, (gid) -> { + outArray[gid] = inArray[gid].length(); + }); + } + + @Test + public void test() { + testGeneratedHsail(); + } + + @Test + public void testUsingLambdaMethod() { + testGeneratedHsailUsingLambdaMethod(); + } + +} diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/lambda/StringUtilsCountMatches2Test.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/lambda/StringUtilsCountMatches2Test.java Mon Apr 28 11:18:15 2014 +0200 @@ -0,0 +1,66 @@ +/* + * Copyright (c) 2009, 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.hsail.test.lambda; + +import static com.oracle.graal.compiler.hsail.test.lambda.StringUtilsCountMatchesTest.*; + +import org.junit.*; + +/** + * Tests calling a method similar to {@code StringUtils.countMatches()} from the Apache commons-lang + * library. The second argument varies per workitem. + */ +public class StringUtilsCountMatches2Test extends CountMatchesBase { + @Override + void setupArrays() { + char[] chars = new char[100]; + for (int i = 0; i < chars.length; i++) { + chars[i] = (char) ('A' + (i % 10)); + } + for (int i = 0; i < NUM; i++) { + inArray[i] = new String(chars, i, (i % 5 + 1)); + } + } + + @Override + public void runTest() { + setupArrays(); + String base = "ABCDE BCDEF CDEFG DEFGH EFGHI FGHIJ ABCDE BCDEF CDEFG DEFGH EFGHI FGHIJ "; + + dispatchLambdaKernel(NUM, (gid) -> { + outArray[gid] = countMatches(base, inArray[gid]); + }); + } + + @Test + public void test() { + testGeneratedHsail(); + } + + @Test + public void testUsingLambdaMethod() { + testGeneratedHsailUsingLambdaMethod(); + } + +} diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/lambda/StringUtilsCountMatchesTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/lambda/StringUtilsCountMatchesTest.java Mon Apr 28 11:18:15 2014 +0200 @@ -0,0 +1,71 @@ +/* + * Copyright (c) 2009, 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.hsail.test.lambda; + +import org.junit.*; + +/** + * Tests calling a method similar to {@code StringUtils.countMatches()} from the Apache commons-lang + * library. The first argument varies per workitem. + */ +public class StringUtilsCountMatchesTest extends CountMatchesBase { + + public static int countMatches(String str, String sub) { + if (isEmpty(str) || isEmpty(sub)) { + return 0; + } + int count = 0; + int idx = 0; + while ((idx = str.indexOf(sub, idx)) != -1) { + count++; + idx += sub.length(); + } + return count; + } + + private static boolean isEmpty(String str) { + return str == null || str.length() == 0; + } + + @Override + public void runTest() { + setupArrays(); + String base = "CDE"; + + dispatchLambdaKernel(NUM, (gid) -> { + outArray[gid] = countMatches(inArray[gid], base); + }); + } + + @Test + public void test() { + testGeneratedHsail(); + } + + @Test + public void testUsingLambdaMethod() { + testGeneratedHsailUsingLambdaMethod(); + } + +} diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/lambda/SynchronizedMethodTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/lambda/SynchronizedMethodTest.java Mon Apr 28 11:18:15 2014 +0200 @@ -0,0 +1,78 @@ +/* + * Copyright (c) 2009, 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.hsail.test.lambda; + +import static com.oracle.graal.debug.Debug.*; + +import com.oracle.graal.compiler.hsail.test.infra.GraalKernelTester; +import com.oracle.graal.debug.*; + +import org.junit.Test; + +/** + * Tests calling a synchronized method. + */ +public class SynchronizedMethodTest extends GraalKernelTester { + + static final int NUM = 20; + @Result public int[] outArray = new int[NUM]; + public int[] inArray = new int[NUM]; + + void setupArrays() { + for (int i = 0; i < NUM; i++) { + inArray[i] = i; + outArray[i] = -i; + } + } + + synchronized int syncSquare(int n) { + return n * n; + } + + @Override + public void runTest() { + setupArrays(); + + dispatchLambdaKernel(NUM, (gid) -> { + outArray[gid] = syncSquare(inArray[gid]); + }); + } + + // cannot handle the BeginLockScope node + @Test(expected = com.oracle.graal.compiler.common.GraalInternalError.class) + public void test() { + try (DebugConfigScope s = disableIntercept()) { + testGeneratedHsail(); + } + } + + // cannot handle the BeginLockScope node + @Test(expected = com.oracle.graal.compiler.common.GraalInternalError.class) + public void testUsingLambdaMethod() { + try (DebugConfigScope s = disableIntercept()) { + testGeneratedHsailUsingLambdaMethod(); + } + } + +} diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/lambda/TooSimpleNewTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/lambda/TooSimpleNewTest.java Mon Apr 28 11:18:15 2014 +0200 @@ -0,0 +1,67 @@ +/* + * Copyright (c) 2009, 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.hsail.test.lambda; + +import com.oracle.graal.compiler.hsail.test.infra.GraalKernelTester; +import org.junit.Test; +import com.oracle.graal.compiler.hsail.test.Vec3; + +/** + * Tests a very simple non-escaping object allocation. + */ +public class TooSimpleNewTest extends GraalKernelTester { + + static final int NUM = 20; + @Result public float[] outArray = new float[NUM]; + public float[] inArray = new float[NUM]; + + void setupArrays() { + for (int i = 0; i < NUM; i++) { + inArray[i] = i; + outArray[i] = -i; + } + } + + @Override + public void runTest() { + setupArrays(); + + dispatchLambdaKernel(NUM, (gid) -> { + float inval = inArray[gid]; + Vec3 vec3 = new Vec3(inval + 1, inval + 2, inval + 3); + outArray[gid] = vec3.x; + }); + } + + @Test + public void test() { + testGeneratedHsail(); + } + + @Test + public void testUsingLambdaMethod() { + testGeneratedHsailUsingLambdaMethod(); + } + +} diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/lambda/TwoDIntArrayTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/lambda/TwoDIntArrayTest.java Mon Apr 28 11:18:15 2014 +0200 @@ -0,0 +1,66 @@ +/* + * Copyright (c) 2009, 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.hsail.test.lambda; + +import com.oracle.graal.compiler.hsail.test.infra.GraalKernelTester; +import org.junit.Test; + +/** + * Tests reading from a 2-D int array. + */ +public class TwoDIntArrayTest extends GraalKernelTester { + + static final int NUM = 20; + @Result public int[] outArray = new int[NUM]; + public int[][] inArray = new int[NUM][NUM]; + + void setupArrays() { + for (int i = 0; i < NUM; i++) { + for (int j = 0; j < NUM; j++) { + inArray[i][j] = i * j; + } + outArray[i] = -i; + } + } + + @Override + public void runTest() { + setupArrays(); + + dispatchLambdaKernel(NUM, (gid) -> { + outArray[gid] = inArray[gid][gid] + 100; + }); + } + + @Test + public void test() { + testGeneratedHsail(); + } + + @Test + public void testUsingLambdaMethod() { + testGeneratedHsailUsingLambdaMethod(); + } + +} diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/lambda/VarArgsTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/lambda/VarArgsTest.java Mon Apr 28 11:18:15 2014 +0200 @@ -0,0 +1,72 @@ +/* + * Copyright (c) 2009, 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.hsail.test.lambda; + +import com.oracle.graal.compiler.hsail.test.infra.GraalKernelTester; +import org.junit.Test; + +/** + * Tests calling a varargs method. + */ +public class VarArgsTest extends GraalKernelTester { + + static final int NUM = 20; + @Result public int[] outArray = new int[NUM]; + public int[] inArray = new int[NUM]; + + void setupArrays() { + for (int i = 0; i < NUM; i++) { + inArray[i] = i; + outArray[i] = -i; + } + } + + int addArgs(Object... args) { + int sum = 0; + for (Object n : args) { + sum += (Integer) n; + } + return sum; + } + + @Override + public void runTest() { + setupArrays(); + + dispatchLambdaKernel(NUM, (gid) -> { + outArray[gid] = (gid > 9 ? addArgs(gid, gid + 1, gid + 2) : addArgs(inArray[gid], gid - 1, gid - 2, gid - 3)); + }); + } + + @Test + public void test() { + testGeneratedHsail(); + } + + @Test + public void testUsingLambdaMethod() { + testGeneratedHsailUsingLambdaMethod(); + } + +} diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/lambda/Vec3ObjStreamFloatCaptureTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/lambda/Vec3ObjStreamFloatCaptureTest.java Mon Apr 28 11:18:15 2014 +0200 @@ -0,0 +1,65 @@ +/* + * Copyright (c) 2009, 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.hsail.test.lambda; + +import com.oracle.graal.compiler.hsail.test.infra.GraalKernelTester; +import org.junit.Test; +import com.oracle.graal.compiler.hsail.test.Vec3; + +/** + * Tests codegen for a java 8 lambda style object array stream kernel, one float capture. + */ +public class Vec3ObjStreamFloatCaptureTest extends GraalKernelTester { + + static final int NUM = 20; + + @Result public Vec3[] inArray = new Vec3[NUM]; + float baseAdjustment = 0.5f; + + void setupArrays() { + for (int i = 0; i < NUM; i++) { + inArray[i] = new Vec3(i, i + 1, -1); + } + } + + @Override + public void runTest() { + setupArrays(); + float adjustment = baseAdjustment; + dispatchLambdaKernel(inArray, obj -> { + Vec3 vec3 = (Vec3) obj; + vec3.z = vec3.x + vec3.y - adjustment; + }); + } + + @Test + public void test() { + testGeneratedHsail(); + } + + @Test + public void testUsingLambdaMethod() { + testGeneratedHsailUsingLambdaMethod(); + } +} diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/lambda/Vec3ObjStreamIntCaptureTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/lambda/Vec3ObjStreamIntCaptureTest.java Mon Apr 28 11:18:15 2014 +0200 @@ -0,0 +1,65 @@ +/* + * Copyright (c) 2009, 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.hsail.test.lambda; + +import com.oracle.graal.compiler.hsail.test.infra.GraalKernelTester; +import org.junit.Test; +import com.oracle.graal.compiler.hsail.test.Vec3; + +/** + * Tests codegen for a java 8 style object array stream kernel, one int capture. + */ +public class Vec3ObjStreamIntCaptureTest extends GraalKernelTester { + + static final int NUM = 20; + + @Result public Vec3[] inArray = new Vec3[NUM]; + int baseAdjustment = 7; + + void setupArrays() { + for (int i = 0; i < NUM; i++) { + inArray[i] = new Vec3(i, i + 1, -1); + } + } + + @Override + public void runTest() { + setupArrays(); + int adjustment = baseAdjustment; + dispatchLambdaKernel(inArray, obj -> { + Vec3 vec3 = (Vec3) obj; + vec3.z = vec3.x + vec3.y - adjustment; + }); + } + + @Test + public void test() { + testGeneratedHsail(); + } + + @Test + public void testUsingLambdaMethod() { + testGeneratedHsailUsingLambdaMethod(); + } +} diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/lambda/Vec3ObjStreamIntFloatCaptureTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/lambda/Vec3ObjStreamIntFloatCaptureTest.java Mon Apr 28 11:18:15 2014 +0200 @@ -0,0 +1,68 @@ +/* + * Copyright (c) 2009, 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.hsail.test.lambda; + +import com.oracle.graal.compiler.hsail.test.infra.GraalKernelTester; +import org.junit.Test; +import com.oracle.graal.compiler.hsail.test.Vec3; + +/** + * Tests codegen for a java 8 style object array stream kernel, one int and one float capture. + */ +public class Vec3ObjStreamIntFloatCaptureTest extends GraalKernelTester { + + static final int NUM = 20; + + @Result public Vec3[] inArray = new Vec3[NUM]; + int baseAdjustment = 7; + float baseMultiplier = 0.5f; + + void setupArrays() { + for (int i = 0; i < NUM; i++) { + inArray[i] = new Vec3(i, i + 1, -1); + } + } + + @Override + public void runTest() { + setupArrays(); + int adjustment = baseAdjustment; + float multiplier = baseMultiplier; + + dispatchLambdaKernel(inArray, obj -> { + Vec3 vec3 = (Vec3) obj; + vec3.z = (vec3.x + vec3.y - adjustment) * multiplier; + }); + } + + @Test + public void test() { + testGeneratedHsail(); + } + + @Test + public void testUsingLambdaMethod() { + testGeneratedHsailUsingLambdaMethod(); + } +} diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/lambda/Vec3ObjStreamObjCaptureTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/lambda/Vec3ObjStreamObjCaptureTest.java Mon Apr 28 11:18:15 2014 +0200 @@ -0,0 +1,65 @@ +/* + * Copyright (c) 2009, 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.hsail.test.lambda; + +import com.oracle.graal.compiler.hsail.test.infra.GraalKernelTester; +import org.junit.Test; +import com.oracle.graal.compiler.hsail.test.Vec3; + +/** + * Tests codegen for a java 8 lambda style object array stream kernel, one object capture. + */ +public class Vec3ObjStreamObjCaptureTest extends GraalKernelTester { + + static final int NUM = 20; + + @Result public Vec3[] inArray = new Vec3[NUM]; + float baseAdjustment = 0.5f; + + void setupArrays() { + for (int i = 0; i < NUM; i++) { + inArray[i] = new Vec3(i, i + 1, -1); + } + } + + @Override + public void runTest() { + setupArrays(); + Vec3 basevec = new Vec3(1, 2, 3); + dispatchLambdaKernel(inArray, obj -> { + Vec3 vec3 = (Vec3) obj; + vec3.z = vec3.x + vec3.y - basevec.z; + }); + } + + @Test + public void test() { + testGeneratedHsail(); + } + + @Test + public void testUsingLambdaMethod() { + testGeneratedHsailUsingLambdaMethod(); + } +} diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/lambda/Vec3ObjStreamObjFieldTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/lambda/Vec3ObjStreamObjFieldTest.java Mon Apr 28 11:18:15 2014 +0200 @@ -0,0 +1,65 @@ +/* + * Copyright (c) 2009, 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.hsail.test.lambda; + +import com.oracle.graal.compiler.hsail.test.infra.GraalKernelTester; +import org.junit.Test; +import com.oracle.graal.compiler.hsail.test.Vec3; + +/** + * Tests codegen for a java 8 style object array stream kernel. Instance method which accesses an + * object field. + */ +public class Vec3ObjStreamObjFieldTest extends GraalKernelTester { + + static final int NUM = 20; + + @Result public Vec3[] inArray = new Vec3[NUM]; + Vec3 basevec = new Vec3(1, 2, 3); + + void setupArrays() { + for (int i = 0; i < NUM; i++) { + inArray[i] = new Vec3(i, i + 1, -1); + } + } + + @Override + public void runTest() { + setupArrays(); + dispatchLambdaKernel(inArray, obj -> { + Vec3 vec3 = (Vec3) obj; + vec3.z = vec3.x + vec3.y - basevec.z; + }); + } + + @Test + public void test() { + testGeneratedHsail(); + } + + @Test + public void testUsingLambdaMethod() { + testGeneratedHsailUsingLambdaMethod(); + } +} diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/lambda/Vec3ObjStreamTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/lambda/Vec3ObjStreamTest.java Mon Apr 28 11:18:15 2014 +0200 @@ -0,0 +1,63 @@ +/* + * Copyright (c) 2009, 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.hsail.test.lambda; + +import com.oracle.graal.compiler.hsail.test.infra.GraalKernelTester; +import org.junit.Test; +import com.oracle.graal.compiler.hsail.test.Vec3; + +/** + * Tests codegen for a java 8 style object array stream kernel, no captures. + */ +public class Vec3ObjStreamTest extends GraalKernelTester { + + static final int NUM = 20; + + @Result public Vec3[] inArray = new Vec3[NUM]; + + void setupArrays() { + for (int i = 0; i < NUM; i++) { + inArray[i] = new Vec3(i, i + 1, -1); + } + } + + @Override + public void runTest() { + setupArrays(); + dispatchLambdaKernel(inArray, obj -> { + Vec3 vec3 = (Vec3) obj; + vec3.z = vec3.x + vec3.y; + }); + } + + @Test + public void test() { + testGeneratedHsail(); + } + + @Test + public void testUsingLambdaMethod() { + testGeneratedHsailUsingLambdaMethod(); + } +} diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/lambda/VecmathNBodyTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/lambda/VecmathNBodyTest.java Mon Apr 28 11:18:15 2014 +0200 @@ -0,0 +1,135 @@ +/* + * Copyright (c) 2009, 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.hsail.test.lambda; + +import java.util.*; +import org.junit.*; +import com.oracle.graal.compiler.hsail.test.infra.GraalKernelTester; +import javax.vecmath.*; + +/** + * Tests NBody algorithm using the javax.vecmath package (all objects non-escaping). + */ +public class VecmathNBodyTest extends GraalKernelTester { + static final int bodies = 1024; + static final float delT = .005f; + static final float espSqr = 1.0f; + static final float mass = 5f; + static final int width = 768; + static final int height = 768; + + static class Body extends Vector3f { + + /** + * + */ + private static final long serialVersionUID = 1L; + + public Body(float _x, float _y, float _z, float _m) { + super(_x, _y, _z); + m = _m; + v = new Vector3f(0, 0, 0); + } + + float m; + Vector3f v; + + public float getM() { + return m; + } + + public Vector3f computeAcc(Body[] in_bodies, float espSqr1, float delT1) { + Vector3f acc = new Vector3f(); + + for (Body b : in_bodies) { + Vector3f d = new Vector3f(); + d.sub(b, this); + float invDist = 1.0f / (float) Math.sqrt(d.lengthSquared() + espSqr1); + float s = b.getM() * invDist * invDist * invDist; + acc.scaleAdd(s, d, acc); + } + + // now return acc scaled by delT + acc.scale(delT1); + return acc; + } + } + + @Result Body[] in_bodies = new Body[bodies]; + @Result Body[] out_bodies = new Body[bodies]; + + static Body[] seed_bodies = new Body[bodies]; + + static { + java.util.Random randgen = new Random(0); + final float maxDist = width / 4; + for (int body = 0; body < bodies; body++) { + final float theta = (float) (randgen.nextFloat() * Math.PI * 2); + final float phi = (float) (randgen.nextFloat() * Math.PI * 2); + final float radius = randgen.nextFloat() * maxDist; + float x = (float) (radius * Math.cos(theta) * Math.sin(phi)) + width / 2; + float y = (float) (radius * Math.sin(theta) * Math.sin(phi)) + height / 2; + float z = (float) (radius * Math.cos(phi)); + seed_bodies[body] = new Body(x, y, z, mass); + } + } + + @Override + public void runTest() { + System.arraycopy(seed_bodies, 0, in_bodies, 0, seed_bodies.length); + for (int b = 0; b < bodies; b++) { + out_bodies[b] = new Body(0, 0, 0, mass); + } + // no local copies of arrays so we make it an instance lambda + + dispatchLambdaKernel(bodies, (gid) -> { + Body inb = in_bodies[gid]; + Body outb = out_bodies[gid]; + Vector3f acc = inb.computeAcc(in_bodies, espSqr, delT); + + Vector3f tmpPos = new Vector3f(); + tmpPos.scaleAdd(delT, inb.v, inb); + tmpPos.scaleAdd(0.5f * delT, acc, tmpPos); + outb.set(tmpPos); + + outb.v.add(inb.v, acc); + }); + } + + @Override + protected boolean supportsRequiredCapabilities() { + return (canHandleDeoptVirtualObjects()); + } + + @Test + public void test() { + testGeneratedHsail(); + } + + @Test + public void testUsingLambdaMethod() { + testGeneratedHsailUsingLambdaMethod(); + } + +} diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/lambda/VectorStreamTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/lambda/VectorStreamTest.java Mon Apr 28 11:18:15 2014 +0200 @@ -0,0 +1,190 @@ +/* + * Copyright (c) 2009, 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.hsail.test.lambda; + +import java.util.Vector; +import java.util.stream.Stream; +import static org.junit.Assert.assertTrue; +import org.junit.Test; + +/** + * Sumatra API tests which use a Stream derived from a Vector. + */ +public class VectorStreamTest { + + // Static and instance fields to test codegen for + // each type of variable + static int staticSize = 16; + final int size = staticSize; + + static int staticFactor = 3; + final int factor = staticFactor; + + class MyPoint { + + int x; + int y; + + public MyPoint(int _x, int _y) { + x = _x; + y = _y; + } + } + + public Vector buildMyPointInputArray() { + Vector inputs = new Vector<>(size); + + for (int i = 0; i < size; i++) { + inputs.add(new MyPoint(i, i + 1)); + } + return inputs; + } + + public int[] buildIntInputArray() { + int[] inputs = new int[size]; + + for (int i = 0; i < size; i++) { + inputs[i] = i * 4; + } + return inputs; + } + + @Test + public void testForEachObjectStreamNoCaptures() { + Vector inputs = buildMyPointInputArray(); + + Stream s = inputs.stream(); + s = s.parallel(); + s.forEach(p -> { + // Swap the values + int tmp = p.x; + p.x = p.y + factor; + p.y = tmp; + }); + + for (int k = 0; k < size; k++) { + MyPoint p = inputs.get(k); + // System.out.println( k + " ... p.x=" + p.x ); + assertTrue(p.x == (p.y + 1 + factor)); + } + } + + @Test + public void testForEachObjectStreamNoCapturesUseStatic() { + Vector inputs = buildMyPointInputArray(); + + Stream s = inputs.stream(); + s = s.parallel(); + s.forEach(p -> { + // Swap the values + int tmp = p.x; + p.x = p.y + staticFactor; + p.y = tmp; + }); + + for (int k = 0; k < size; k++) { + MyPoint p = inputs.get(k); + // System.out.println( k + " ... p.x=" + p.x ); + assertTrue(p.x == (p.y + 1 + staticFactor)); + } + } + + @Test + public void testForEachObjectStreamOneCapture() { + int[] data = buildIntInputArray(); + Vector inputs = buildMyPointInputArray(); + + Stream s = inputs.stream(); + s = s.parallel(); + s.forEach(p -> { + p.y = data[p.x]; + }); + + for (int k = 0; k < size; k++) { + MyPoint p = inputs.get(k); + // System.out.println( k + " ... p.x=" + p.x ); + assertTrue(p.y == data[p.x]); + } + + } + + @Test + public void testForEachObjectStreamOneCaptureUseStatic() { + int[] data = buildIntInputArray(); + Vector inputs = buildMyPointInputArray(); + + Stream s = inputs.stream(); + s = s.parallel(); + s.forEach(p -> { + p.y = data[p.x] + staticFactor; + }); + + for (int k = 0; k < size; k++) { + MyPoint p = inputs.get(k); + // System.out.println( k + " ... p.x=" + p.x ); + assertTrue(p.y == (data[p.x] + +staticFactor)); + } + + } + + @Test + public void testForEachObjectStreamTwoCaptures() { + int[] data = buildIntInputArray(); + int[] data2 = buildIntInputArray(); + Vector inputs = buildMyPointInputArray(); + + Stream s = inputs.stream(); + s = s.parallel(); + s.forEach(p -> { + p.y = data[p.x] + data2[p.x]; + }); + + for (int k = 0; k < size; k++) { + MyPoint p = inputs.get(k); + // System.out.println( k + " ... p.x=" + p.x ); + assertTrue(p.y == data[p.x] + data2[p.x]); + } + + } + + @Test + public void testForEachObjectStreamTwoCapturesUseStatic() { + int[] data = buildIntInputArray(); + int[] data2 = buildIntInputArray(); + Vector inputs = buildMyPointInputArray(); + + Stream s = inputs.stream(); + s = s.parallel(); + s.forEach(p -> { + p.y = data[p.x] + data2[p.x] + staticFactor; + }); + + for (int k = 0; k < size; k++) { + MyPoint p = inputs.get(k); + // System.out.println( k + " ... p.x=" + p.x ); + assertTrue(p.y == data[p.x] + data2[p.x] + staticFactor); + } + + } +} diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/lambda/VirtualCallTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/lambda/VirtualCallTest.java Mon Apr 28 11:18:15 2014 +0200 @@ -0,0 +1,111 @@ +/* + * Copyright (c) 2009, 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.hsail.test.lambda; + +import static com.oracle.graal.debug.Debug.*; + +import com.oracle.graal.compiler.hsail.test.infra.GraalKernelTester; +import com.oracle.graal.debug.*; + +import org.junit.Test; + +/** + * Tests a true virtual method call. + */ +public class VirtualCallTest extends GraalKernelTester { + + static final int NUM = 20; + + static abstract class Shape { + + abstract public float getArea(); + } + + static class Circle extends Shape { + + private float radius; + + Circle(float r) { + radius = r; + } + + @Override + public float getArea() { + return (float) (Math.PI * radius * radius); + } + } + + static class Square extends Shape { + + private float len; + + Square(float _len) { + len = _len; + } + + @Override + public float getArea() { + return len * len; + } + } + + @Result public float[] outArray = new float[NUM]; + public Shape[] inShapeArray = new Shape[NUM]; + + void setupArrays() { + for (int i = 0; i < NUM; i++) { + if (i % 2 == 0) + inShapeArray[i] = new Circle(i + 1); + else + inShapeArray[i] = new Square(i + 1); + outArray[i] = -i; + } + } + + @Override + public void runTest() { + setupArrays(); + + dispatchLambdaKernel(NUM, (gid) -> { + Shape shape = inShapeArray[gid]; + outArray[gid] = shape.getArea(); + }); + } + + // graal says not inlining getArea():float (0 bytes): no type profile exists + @Test(expected = com.oracle.graal.compiler.common.GraalInternalError.class) + public void test() { + try (DebugConfigScope s = disableIntercept()) { + testGeneratedHsail(); + } + } + + @Test(expected = com.oracle.graal.compiler.common.GraalInternalError.class) + public void testUsingLambdaMethod() { + try (DebugConfigScope s = disableIntercept()) { + testGeneratedHsailUsingLambdaMethod(); + } + } + +} diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.compiler.hsail/src/com/oracle/graal/compiler/hsail/HSAILLIRGenerator.java --- a/graal/com.oracle.graal.compiler.hsail/src/com/oracle/graal/compiler/hsail/HSAILLIRGenerator.java Fri Apr 25 16:21:07 2014 +0200 +++ b/graal/com.oracle.graal.compiler.hsail/src/com/oracle/graal/compiler/hsail/HSAILLIRGenerator.java Mon Apr 28 11:18:15 2014 +0200 @@ -31,10 +31,11 @@ import com.oracle.graal.api.code.*; import com.oracle.graal.api.meta.*; import com.oracle.graal.asm.*; -import com.oracle.graal.compiler.gen.*; -import com.oracle.graal.graph.*; +import com.oracle.graal.compiler.common.*; +import com.oracle.graal.compiler.common.calc.*; import com.oracle.graal.lir.*; import com.oracle.graal.lir.StandardOp.JumpOp; +import com.oracle.graal.lir.gen.*; import com.oracle.graal.lir.hsail.*; import com.oracle.graal.lir.hsail.HSAILArithmetic.ConvertOp; import com.oracle.graal.lir.hsail.HSAILArithmetic.Op1Stack; @@ -50,9 +51,6 @@ import com.oracle.graal.lir.hsail.HSAILMove.MembarOp; import com.oracle.graal.lir.hsail.HSAILMove.MoveFromRegOp; import com.oracle.graal.lir.hsail.HSAILMove.MoveToRegOp; -import com.oracle.graal.nodes.*; -import com.oracle.graal.nodes.calc.*; -import com.oracle.graal.nodes.calc.FloatConvertNode.FloatConvert; import com.oracle.graal.phases.util.*; /** @@ -148,8 +146,7 @@ finalDisp += asConstant(index).asLong() * scale; } else { Value indexRegister; - Value convertedIndex; - convertedIndex = this.emitSignExtend(index, 32, 64); + Value convertedIndex = index.getKind() == Kind.Long ? index : this.emitSignExtend(index, 32, 64); if (scale != 1) { indexRegister = emitUMul(convertedIndex, Constant.forInt(scale)); } else { @@ -221,7 +218,9 @@ @Override public void emitIntegerTestBranch(Value left, Value right, LabelRef trueDestination, LabelRef falseDestination, double trueDestinationProbability) { - throw GraalInternalError.unimplemented(); + Variable result = emitAnd(left, right); + Variable dummyResult = newVariable(left.getKind()); + append(new CompareBranchOp(mapKindToCompareOp(left.getKind()), Condition.EQ, result, Constant.forInt(0), dummyResult, dummyResult, trueDestination, falseDestination, false)); } @Override @@ -415,7 +414,7 @@ } @Override - public Value emitDiv(Value a, Value b, DeoptimizingNode deopting) { + public Value emitDiv(Value a, Value b, LIRFrameState state) { Variable result = newVariable(a.getKind()); switch (a.getKind()) { case Int: @@ -438,7 +437,7 @@ } @Override - public Value emitRem(Value a, Value b, DeoptimizingNode deopting) { + public Value emitRem(Value a, Value b, LIRFrameState state) { Variable result = newVariable(a.getKind()); switch (a.getKind()) { case Int: @@ -460,12 +459,12 @@ } @Override - public Variable emitUDiv(Value a, Value b, DeoptimizingNode deopting) { + public Variable emitUDiv(Value a, Value b, LIRFrameState state) { throw GraalInternalError.unimplemented(); } @Override - public Variable emitURem(Value a, Value b, DeoptimizingNode deopting) { + public Variable emitURem(Value a, Value b, LIRFrameState state) { throw GraalInternalError.unimplemented(); } @@ -683,7 +682,7 @@ } @Override - public void emitDeoptimize(Value actionAndReason, Value speculation, DeoptimizingNode deopting) { + public void emitDeoptimize(Value actionAndReason, Value speculation, LIRFrameState state) { append(new ReturnOp(Value.ILLEGAL)); } @@ -830,7 +829,7 @@ * Graal generates for any switch construct appearing in Java bytecode. */ @Override - protected void emitStrategySwitch(Constant[] keyConstants, double[] keyProbabilities, LabelRef[] keyTargets, LabelRef defaultTarget, Variable value) { + public void emitStrategySwitch(Constant[] keyConstants, double[] keyProbabilities, LabelRef[] keyTargets, LabelRef defaultTarget, Variable value) { emitStrategySwitch(new SwitchStrategy.SequentialStrategy(keyProbabilities, keyConstants), value, keyTargets, defaultTarget); } @@ -855,7 +854,7 @@ * @param key the key that is compared against the key constants in the case statements. */ @Override - protected void emitStrategySwitch(SwitchStrategy strategy, Variable key, LabelRef[] keyTargets, LabelRef defaultTarget) { + public void emitStrategySwitch(SwitchStrategy strategy, Variable key, LabelRef[] keyTargets, LabelRef defaultTarget) { if ((key.getKind() == Kind.Int) || (key.getKind() == Kind.Long)) { // Append the LIR instruction for generating compare and branch instructions. append(new StrategySwitchOp(strategy, keyTargets, defaultTarget, key)); diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.compiler.hsail/src/com/oracle/graal/compiler/hsail/HSAILNodeLIRBuilder.java --- a/graal/com.oracle.graal.compiler.hsail/src/com/oracle/graal/compiler/hsail/HSAILNodeLIRBuilder.java Fri Apr 25 16:21:07 2014 +0200 +++ b/graal/com.oracle.graal.compiler.hsail/src/com/oracle/graal/compiler/hsail/HSAILNodeLIRBuilder.java Mon Apr 28 11:18:15 2014 +0200 @@ -24,20 +24,20 @@ package com.oracle.graal.compiler.hsail; import com.oracle.graal.api.meta.*; +import com.oracle.graal.compiler.common.*; +import com.oracle.graal.compiler.common.type.*; import com.oracle.graal.compiler.gen.*; -import com.oracle.graal.debug.*; -import com.oracle.graal.graph.*; import com.oracle.graal.lir.*; +import com.oracle.graal.lir.gen.*; import com.oracle.graal.lir.hsail.*; import com.oracle.graal.nodes.*; -import com.oracle.graal.nodes.type.*; /** * This class implements the HSAIL specific portion of the LIR generator. */ public abstract class HSAILNodeLIRBuilder extends NodeLIRBuilder { - public HSAILNodeLIRBuilder(StructuredGraph graph, LIRGenerator lirGen) { + public HSAILNodeLIRBuilder(StructuredGraph graph, LIRGeneratorTool lirGen) { super(graph, lirGen); } @@ -63,20 +63,16 @@ } @Override - public void visitSafepointNode(SafepointNode i) { - Debug.log("visitSafePointNode unimplemented"); - } - - @Override public void emitNullCheck(ValueNode v, DeoptimizingNode deopting) { assert v.stamp() instanceof ObjectStamp; Variable obj = newVariable(Kind.Object); gen.emitMove(obj, operand(v)); - append(new HSAILMove.NullCheckOp(obj, gen.state(deopting))); + append(new HSAILMove.NullCheckOp(obj, state(deopting))); } @Override public void visitInfopointNode(InfopointNode i) { + // TODO Auto-generated method stub throw GraalInternalError.unimplemented(); } } diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.compiler.ptx.test/src/com/oracle/graal/compiler/ptx/test/ControlPTXTest.java --- a/graal/com.oracle.graal.compiler.ptx.test/src/com/oracle/graal/compiler/ptx/test/ControlPTXTest.java Fri Apr 25 16:21:07 2014 +0200 +++ b/graal/com.oracle.graal.compiler.ptx.test/src/com/oracle/graal/compiler/ptx/test/ControlPTXTest.java Mon Apr 28 11:18:15 2014 +0200 @@ -35,6 +35,7 @@ test("testIfElse2I", 19, 64); } + @Ignore("PTXHotSpotLIRGenerator.emitCompress is unimplemented") @Test public void testControl2() { compileKernel("testStatic"); diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.compiler.ptx/src/com/oracle/graal/compiler/ptx/PTXLIRGenerator.java --- a/graal/com.oracle.graal.compiler.ptx/src/com/oracle/graal/compiler/ptx/PTXLIRGenerator.java Fri Apr 25 16:21:07 2014 +0200 +++ b/graal/com.oracle.graal.compiler.ptx/src/com/oracle/graal/compiler/ptx/PTXLIRGenerator.java Mon Apr 28 11:18:15 2014 +0200 @@ -32,10 +32,12 @@ import com.oracle.graal.api.code.*; import com.oracle.graal.api.meta.*; import com.oracle.graal.asm.*; -import com.oracle.graal.compiler.gen.*; -import com.oracle.graal.graph.*; +import com.oracle.graal.compiler.common.*; +import com.oracle.graal.compiler.common.calc.*; +import com.oracle.graal.compiler.common.type.*; import com.oracle.graal.lir.*; import com.oracle.graal.lir.StandardOp.JumpOp; +import com.oracle.graal.lir.gen.*; import com.oracle.graal.lir.ptx.*; import com.oracle.graal.lir.ptx.PTXArithmetic.ConvertOp; import com.oracle.graal.lir.ptx.PTXArithmetic.Op1Stack; @@ -57,11 +59,6 @@ import com.oracle.graal.lir.ptx.PTXMemOp.StoreReturnValOp; import com.oracle.graal.lir.ptx.PTXMove.MoveFromRegOp; import com.oracle.graal.lir.ptx.PTXMove.MoveToRegOp; -import com.oracle.graal.nodes.*; -import com.oracle.graal.nodes.calc.*; -import com.oracle.graal.nodes.calc.FloatConvertNode.FloatConvert; -import com.oracle.graal.nodes.extended.*; -import com.oracle.graal.nodes.type.*; import com.oracle.graal.phases.util.*; /** @@ -232,25 +229,17 @@ } @Override - public Variable emitLoad(PlatformKind kind, Value address, Access access) { + public Variable emitLoad(PlatformKind kind, Value address, LIRFrameState state) { PTXAddressValue loadAddress = asAddress(address); Variable result = newVariable(kind); - LIRFrameState state = null; - if (access instanceof DeoptimizingNode) { - state = state((DeoptimizingNode) access); - } append(new LoadOp((Kind) kind, result, loadAddress, state)); return result; } @Override - public void emitStore(PlatformKind kind, Value address, Value inputVal, Access access) { + public void emitStore(PlatformKind kind, Value address, Value inputVal, LIRFrameState state) { PTXAddressValue storeAddress = asAddress(address); Variable input = load(inputVal); - LIRFrameState state = null; - if (access instanceof DeoptimizingNode) { - state = state((DeoptimizingNode) access); - } append(new StoreOp((Kind) kind, storeAddress, input, state)); } @@ -376,7 +365,6 @@ @Override public Variable emitIntegerTestMove(Value left, Value right, Value trueValue, Value falseValue) { - emitIntegerTest(left, right); Variable result = newVariable(trueValue.getKind()); append(new CondMoveOp(result, Condition.EQ, load(trueValue), loadNonConst(falseValue), nextPredRegNum)); @@ -386,7 +374,6 @@ } private void emitIntegerTest(Value a, Value b) { - assert a.getKind().isNumericInteger(); if (LIRValueUtil.isVariable(b)) { @@ -498,7 +485,7 @@ } @Override - public Value emitDiv(Value a, Value b, DeoptimizingNode deopting) { + public Value emitDiv(Value a, Value b, LIRFrameState state) { Variable result = newVariable(a.getKind()); switch (a.getKind()) { case Int: @@ -520,7 +507,7 @@ } @Override - public Value emitRem(Value a, Value b, DeoptimizingNode deopting) { + public Value emitRem(Value a, Value b, LIRFrameState state) { Variable result = newVariable(a.getKind()); switch (a.getKind()) { case Int: @@ -536,12 +523,12 @@ } @Override - public Variable emitUDiv(Value a, Value b, DeoptimizingNode deopting) { + public Variable emitUDiv(Value a, Value b, LIRFrameState state) { throw GraalInternalError.unimplemented("PTXLIRGenerator.emitUDiv()"); } @Override - public Variable emitURem(Value a, Value b, DeoptimizingNode deopting) { + public Variable emitURem(Value a, Value b, LIRFrameState state) { throw GraalInternalError.unimplemented("PTXLIRGenerator.emitURem()"); } @@ -555,7 +542,6 @@ case Long: append(new Op2Stack(LAND, result, a, loadNonConst(b))); break; - default: throw GraalInternalError.shouldNotReachHere("missing: " + a.getKind()); } @@ -754,7 +740,7 @@ } @Override - public void emitDeoptimize(Value actionAndReason, Value speculation, DeoptimizingNode deopting) { + public void emitDeoptimize(Value actionAndReason, Value speculation, LIRFrameState state) { append(new ReturnOp(Value.ILLEGAL)); } @@ -830,13 +816,12 @@ @Override public void emitReturn(Value input) { - AllocatableValue operand = Value.ILLEGAL; if (input != null) { - operand = resultOperandFor(input.getKind()); + AllocatableValue operand = resultOperandFor(input.getKind()); // Load the global memory address from return parameter Variable loadVar = emitLoadReturnAddress(operand.getKind(), operand, null); - // Store result in global memory whose location is loadVar - emitStoreReturnValue(operand.getKind(), loadVar, operand, null); + // Store input in global memory whose location is loadVar + emitStoreReturnValue(operand.getKind(), loadVar, input, null); } emitReturnNoVal(); } @@ -846,7 +831,7 @@ } @Override - protected void emitStrategySwitch(SwitchStrategy strategy, Variable key, LabelRef[] keyTargets, LabelRef defaultTarget) { + public void emitStrategySwitch(SwitchStrategy strategy, Variable key, LabelRef[] keyTargets, LabelRef defaultTarget) { boolean needsTemp = key.getKind() == Kind.Object; append(new StrategySwitchOp(strategy, keyTargets, defaultTarget, key, needsTemp ? newVariable(key.getKind()) : Value.ILLEGAL, nextPredRegNum++)); } @@ -864,17 +849,16 @@ throw GraalInternalError.unimplemented("PTXLIRGenerator.emitUnwind()"); } - public Variable emitLoadParam(Kind kind, Value address, DeoptimizingNode deopting) { + public Variable emitLoadParam(Kind kind, Value address, LIRFrameState state) { PTXAddressValue loadAddress = asAddress(address); Variable result = newVariable(kind); - append(new LoadParamOp(kind, result, loadAddress, deopting != null ? state(deopting) : null)); + append(new LoadParamOp(kind, result, loadAddress, state)); return result; } - public Variable emitLoadReturnAddress(Kind kind, Value address, DeoptimizingNode deopting) { - + public Variable emitLoadReturnAddress(Kind kind, Value address, LIRFrameState state) { PTXAddressValue loadAddress = asAddress(address); Variable result; switch (kind) { @@ -886,18 +870,16 @@ break; default: result = newVariable(kind); - } - append(new LoadReturnAddrOp(kind, result, loadAddress, deopting != null ? state(deopting) : null)); + append(new LoadReturnAddrOp(kind, result, loadAddress, state)); return result; } - public void emitStoreReturnValue(Kind kind, Value address, Value inputVal, DeoptimizingNode deopting) { - + public void emitStoreReturnValue(Kind kind, Value address, Value inputVal, LIRFrameState state) { PTXAddressValue storeAddress = asAddress(address); Variable input = load(inputVal); - append(new StoreReturnValOp(kind, storeAddress, input, deopting != null ? state(deopting) : null)); + append(new StoreReturnValOp(kind, storeAddress, input, state)); } @Override @@ -909,6 +891,7 @@ } public Value emitCompareAndSwap(Value address, Value expectedValue, Value newValue, Value trueValue, Value falseValue) { - throw GraalInternalError.unimplemented("PTXLIRGenerator.emitCompareAndSwap()"); + throw GraalInternalError.unimplemented(); } + } diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.compiler.ptx/src/com/oracle/graal/compiler/ptx/PTXNodeLIRBuilder.java --- a/graal/com.oracle.graal.compiler.ptx/src/com/oracle/graal/compiler/ptx/PTXNodeLIRBuilder.java Fri Apr 25 16:21:07 2014 +0200 +++ b/graal/com.oracle.graal.compiler.ptx/src/com/oracle/graal/compiler/ptx/PTXNodeLIRBuilder.java Mon Apr 28 11:18:15 2014 +0200 @@ -27,10 +27,11 @@ import com.oracle.graal.api.code.*; import com.oracle.graal.api.meta.*; +import com.oracle.graal.compiler.common.*; import com.oracle.graal.compiler.gen.*; import com.oracle.graal.debug.*; -import com.oracle.graal.graph.*; import com.oracle.graal.lir.*; +import com.oracle.graal.lir.gen.*; import com.oracle.graal.lir.ptx.*; import com.oracle.graal.nodes.*; @@ -55,7 +56,7 @@ } } - public PTXNodeLIRBuilder(StructuredGraph graph, LIRGenerator lirGen) { + public PTXNodeLIRBuilder(StructuredGraph graph, LIRGeneratorTool lirGen) { super(graph, lirGen); } @@ -135,7 +136,7 @@ @Override public void emitNullCheck(ValueNode v, DeoptimizingNode deopting) { assert v.getKind() == Kind.Object; - append(new PTXMove.NullCheckOp(gen.load(operand(v)), gen.state(deopting))); + append(new PTXMove.NullCheckOp(gen.load(operand(v)), state(deopting))); } @Override diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.compiler.sparc/src/com/oracle/graal/compiler/sparc/SPARCLIRGenerator.java --- a/graal/com.oracle.graal.compiler.sparc/src/com/oracle/graal/compiler/sparc/SPARCLIRGenerator.java Fri Apr 25 16:21:07 2014 +0200 +++ b/graal/com.oracle.graal.compiler.sparc/src/com/oracle/graal/compiler/sparc/SPARCLIRGenerator.java Mon Apr 28 11:18:15 2014 +0200 @@ -27,40 +27,21 @@ import static com.oracle.graal.lir.sparc.SPARCArithmetic.*; import static com.oracle.graal.lir.sparc.SPARCBitManipulationOp.IntrinsicOpcode.*; import static com.oracle.graal.lir.sparc.SPARCCompare.*; +import static com.oracle.graal.lir.sparc.SPARCControlFlow.*; import static com.oracle.graal.lir.sparc.SPARCMathIntrinsicOp.IntrinsicOpcode.*; +import static com.oracle.graal.lir.sparc.SPARCMove.*; import com.oracle.graal.api.code.*; import com.oracle.graal.api.meta.*; import com.oracle.graal.asm.*; import com.oracle.graal.asm.sparc.*; -import com.oracle.graal.compiler.gen.*; -import com.oracle.graal.graph.*; +import com.oracle.graal.compiler.common.*; +import com.oracle.graal.compiler.common.calc.*; +import com.oracle.graal.compiler.common.type.*; import com.oracle.graal.lir.*; import com.oracle.graal.lir.StandardOp.JumpOp; +import com.oracle.graal.lir.gen.*; import com.oracle.graal.lir.sparc.*; -import com.oracle.graal.lir.sparc.SPARCArithmetic.BinaryCommutative; -import com.oracle.graal.lir.sparc.SPARCArithmetic.BinaryRegConst; -import com.oracle.graal.lir.sparc.SPARCArithmetic.BinaryRegReg; -import com.oracle.graal.lir.sparc.SPARCArithmetic.Op1Stack; -import com.oracle.graal.lir.sparc.SPARCArithmetic.Op2Stack; -import com.oracle.graal.lir.sparc.SPARCArithmetic.RemOp; -import com.oracle.graal.lir.sparc.SPARCArithmetic.Unary2Op; -import com.oracle.graal.lir.sparc.SPARCCompare.CompareOp; -import com.oracle.graal.lir.sparc.SPARCControlFlow.BranchOp; -import com.oracle.graal.lir.sparc.SPARCControlFlow.CondMoveOp; -import com.oracle.graal.lir.sparc.SPARCControlFlow.FloatCondMoveOp; -import com.oracle.graal.lir.sparc.SPARCControlFlow.ReturnOp; -import com.oracle.graal.lir.sparc.SPARCControlFlow.StrategySwitchOp; -import com.oracle.graal.lir.sparc.SPARCControlFlow.TableSwitchOp; -import com.oracle.graal.lir.sparc.SPARCMove.LoadAddressOp; -import com.oracle.graal.lir.sparc.SPARCMove.MembarOp; -import com.oracle.graal.lir.sparc.SPARCMove.MoveFromRegOp; -import com.oracle.graal.lir.sparc.SPARCMove.MoveToRegOp; -import com.oracle.graal.lir.sparc.SPARCMove.StackLoadAddressOp; -import com.oracle.graal.nodes.*; -import com.oracle.graal.nodes.calc.*; -import com.oracle.graal.nodes.calc.FloatConvertNode.FloatConvert; -import com.oracle.graal.nodes.type.*; import com.oracle.graal.phases.util.*; /** @@ -131,7 +112,7 @@ @Override public void emitData(AllocatableValue dst, byte[] data) { - throw GraalInternalError.unimplemented(); + append(new LoadDataAddressOp(dst, data)); } @Override @@ -158,7 +139,7 @@ indexRegister = Value.ILLEGAL; } else { if (scale != 1) { - Value longIndex = emitSignExtend(index, 32, 64); + Value longIndex = index.getKind() == Kind.Long ? index : emitSignExtend(index, 32, 64); if (CodeUtil.isPowerOf2(scale)) { indexRegister = emitShl(longIndex, Constant.forLong(CodeUtil.log2(scale))); } else { @@ -186,16 +167,20 @@ // If we don't have an index register we can use a displacement, otherwise load the // displacement into a register and add it to the base. if (indexRegister.equals(Value.ILLEGAL)) { - // TODO What if displacement if too big? displacementInt = (int) finalDisp; + assert SPARCAssembler.isSimm13(displacementInt) : displacementInt; } else { displacementInt = 0; if (baseRegister.equals(Value.ILLEGAL)) { baseRegister = load(Constant.forLong(finalDisp)); } else { - Variable longBaseRegister = newVariable(Kind.Long); - emitMove(longBaseRegister, baseRegister); // FIXME get rid of this move - baseRegister = emitAdd(longBaseRegister, Constant.forLong(finalDisp)); + if (finalDisp == 0) { + // Nothing to do. Just use the base register. + } else { + Variable longBaseRegister = newVariable(Kind.Long); + emitMove(longBaseRegister, baseRegister); + baseRegister = emitAdd(longBaseRegister, Constant.forLong(finalDisp)); + } } } @@ -284,15 +269,16 @@ Condition finalCondition = mirrored ? cond.mirror() : cond; Variable result = newVariable(trueValue.getKind()); - switch (left.getKind().getStackKind()) { + Kind kind = left.getKind().getStackKind(); + switch (kind) { case Int: case Long: case Object: - append(new CondMoveOp(result, finalCondition, load(trueValue), loadNonConst(falseValue))); + append(new CondMoveOp(kind, result, finalCondition, load(trueValue), loadNonConst(falseValue))); break; case Float: case Double: - append(new FloatCondMoveOp(result, finalCondition, unorderedIsTrue, load(trueValue), load(falseValue))); + append(new FloatCondMoveOp(kind, result, finalCondition, unorderedIsTrue, load(trueValue), load(falseValue))); break; default: throw GraalInternalError.shouldNotReachHere("" + left.getKind()); @@ -347,7 +333,8 @@ public Variable emitIntegerTestMove(Value left, Value right, Value trueValue, Value falseValue) { emitIntegerTest(left, right); Variable result = newVariable(trueValue.getKind()); - append(new CondMoveOp(result, Condition.EQ, load(trueValue), loadNonConst(falseValue))); + Kind kind = left.getKind().getStackKind(); + append(new CondMoveOp(kind, result, Condition.EQ, load(trueValue), loadNonConst(falseValue))); return result; } @@ -362,7 +349,7 @@ } @Override - protected void emitStrategySwitch(SwitchStrategy strategy, Variable key, LabelRef[] keyTargets, LabelRef defaultTarget) { + public void emitStrategySwitch(SwitchStrategy strategy, Variable key, LabelRef[] keyTargets, LabelRef defaultTarget) { // a temp is needed for loading long and object constants boolean needsTemp = key.getKind() == Kind.Long || key.getKind() == Kind.Object; append(new StrategySwitchOp(strategy, keyTargets, defaultTarget, key, needsTemp ? newVariable(key.getKind()) : Value.ILLEGAL)); @@ -593,7 +580,7 @@ } @Override - public Value emitDiv(Value a, Value b, DeoptimizingNode deopting) { + public Value emitDiv(Value a, Value b, LIRFrameState state) { Variable result = newVariable(a.getKind()); switch (a.getKind().getStackKind()) { case Int: @@ -615,8 +602,7 @@ } @Override - public Value emitRem(Value a, Value b, DeoptimizingNode deopting) { - LIRFrameState state = state(deopting); + public Value emitRem(Value a, Value b, LIRFrameState state) { Variable result = newVariable(a.getKind()); switch (a.getKind().getStackKind()) { case Int: @@ -632,7 +618,7 @@ } @Override - public Value emitUDiv(Value a, Value b, DeoptimizingNode deopting) { + public Value emitUDiv(Value a, Value b, LIRFrameState state) { // LIRFrameState state = state(deopting); switch (a.getKind().getStackKind()) { case Int: @@ -647,7 +633,7 @@ } @Override - public Value emitURem(Value a, Value b, DeoptimizingNode deopting) { + public Value emitURem(Value a, Value b, LIRFrameState state) { // LIRFrameState state = state(deopting); switch (a.getKind().getStackKind()) { case Int: @@ -814,22 +800,23 @@ return inputVal; } else if (toBits > 32) { // sign extend to 64 bits - if (fromBits == 32) { - return emitConvert2Op(Kind.Long, I2L, asAllocatable(inputVal)); - } else if (fromBits < 32) { - // TODO implement direct x2L sign extension conversions - Value intVal = emitSignExtend(inputVal, fromBits, 32); - return emitSignExtend(intVal, 32, toBits); - } else { - throw GraalInternalError.unimplemented("unsupported sign extension (" + fromBits + " bit -> " + toBits + " bit)"); + switch (fromBits) { + case 8: + return emitConvert2Op(Kind.Long, B2L, asAllocatable(inputVal)); + case 16: + return emitConvert2Op(Kind.Long, S2L, asAllocatable(inputVal)); + case 32: + return emitConvert2Op(Kind.Long, I2L, asAllocatable(inputVal)); + default: + throw GraalInternalError.unimplemented("unsupported sign extension (" + fromBits + " bit -> " + toBits + " bit)"); } } else { // sign extend to 32 bits (smaller values are internally represented as 32 bit values) switch (fromBits) { case 8: - return emitConvert2Op(Kind.Int, I2B, asAllocatable(inputVal)); + return emitConvert2Op(Kind.Int, B2I, asAllocatable(inputVal)); case 16: - return emitConvert2Op(Kind.Int, I2S, asAllocatable(inputVal)); + return emitConvert2Op(Kind.Int, S2I, asAllocatable(inputVal)); case 32: return inputVal; default: @@ -917,7 +904,7 @@ } @Override - public void emitDeoptimize(Value actionAndReason, Value speculation, DeoptimizingNode deopting) { + public void emitDeoptimize(Value actionAndReason, Value speculation, LIRFrameState state) { append(new ReturnOp(Value.ILLEGAL)); } diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.compiler.sparc/src/com/oracle/graal/compiler/sparc/SPARCNodeLIRBuilder.java --- a/graal/com.oracle.graal.compiler.sparc/src/com/oracle/graal/compiler/sparc/SPARCNodeLIRBuilder.java Fri Apr 25 16:21:07 2014 +0200 +++ b/graal/com.oracle.graal.compiler.sparc/src/com/oracle/graal/compiler/sparc/SPARCNodeLIRBuilder.java Mon Apr 28 11:18:15 2014 +0200 @@ -25,7 +25,9 @@ import com.oracle.graal.api.code.*; import com.oracle.graal.api.meta.*; +import com.oracle.graal.compiler.common.*; import com.oracle.graal.compiler.gen.*; +import com.oracle.graal.lir.gen.*; import com.oracle.graal.lir.sparc.*; import com.oracle.graal.lir.sparc.SPARCMove.NullCheckOp; import com.oracle.graal.nodes.*; @@ -35,7 +37,7 @@ */ public abstract class SPARCNodeLIRBuilder extends NodeLIRBuilder { - public SPARCNodeLIRBuilder(StructuredGraph graph, LIRGenerator lirGen) { + public SPARCNodeLIRBuilder(StructuredGraph graph, LIRGeneratorTool lirGen) { super(graph, lirGen); } @@ -59,11 +61,12 @@ @Override public void emitNullCheck(ValueNode v, DeoptimizingNode deopting) { assert v.getKind() == Kind.Object; - append(new NullCheckOp(gen.load(operand(v)), gen.state(deopting))); + append(new NullCheckOp(gen.load(operand(v)), state(deopting))); } @Override public void visitInfopointNode(InfopointNode i) { - throw new InternalError("NYI"); + // TODO Auto-generated method stub + throw GraalInternalError.unimplemented(); } } diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/CheckGraalInvariants.java --- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/CheckGraalInvariants.java Fri Apr 25 16:21:07 2014 +0200 +++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/CheckGraalInvariants.java Mon Apr 28 11:18:15 2014 +0200 @@ -22,6 +22,8 @@ */ package com.oracle.graal.compiler.test; +import static com.oracle.graal.debug.DelegatingDebugConfig.Feature.*; + import java.io.*; import java.lang.reflect.*; import java.util.*; @@ -33,7 +35,6 @@ import com.oracle.graal.api.meta.*; import com.oracle.graal.api.runtime.*; import com.oracle.graal.debug.*; -import com.oracle.graal.debug.internal.*; import com.oracle.graal.java.*; import com.oracle.graal.nodes.*; import com.oracle.graal.phases.*; @@ -42,13 +43,14 @@ import com.oracle.graal.phases.util.*; import com.oracle.graal.phases.verify.*; import com.oracle.graal.runtime.*; +import com.oracle.graal.test.*; /** * Checks that all classes in graal.jar (which must be on the class path) comply with global * invariants such as using {@link Object#equals(Object)} to compare certain types instead of * identity comparisons. */ -public class CheckGraalInvariants { +public class CheckGraalInvariants extends GraalTest { @Test public void test() { @@ -106,14 +108,7 @@ String methodName = className + "." + m.getName(); if (matches(filters, methodName)) { StructuredGraph graph = new StructuredGraph(metaAccess.lookupJavaMethod(m)); - DebugConfig debugConfig = DebugScope.getConfig(); - DebugConfig noInterceptConfig = new DelegatingDebugConfig(debugConfig) { - @Override - public RuntimeException interceptException(Throwable e) { - return null; - } - }; - try (DebugConfigScope s = Debug.setConfig(noInterceptConfig)) { + try (DebugConfigScope s = Debug.setConfig(new DelegatingDebugConfig().disable(INTERCEPT))) { graphBuilderSuite.apply(graph, context); checkGraph(context, graph); } catch (VerificationError e) { diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ConditionTest.java --- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ConditionTest.java Fri Apr 25 16:21:07 2014 +0200 +++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ConditionTest.java Mon Apr 28 11:18:15 2014 +0200 @@ -29,7 +29,7 @@ import org.junit.*; import com.oracle.graal.api.meta.*; -import com.oracle.graal.nodes.calc.*; +import com.oracle.graal.compiler.common.calc.*; public class ConditionTest { diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ConditionalEliminationTest.java --- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ConditionalEliminationTest.java Fri Apr 25 16:21:07 2014 +0200 +++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ConditionalEliminationTest.java Mon Apr 28 11:18:15 2014 +0200 @@ -22,23 +22,16 @@ */ package com.oracle.graal.compiler.test; -import static com.oracle.graal.nodes.ConstantNode.*; -import static com.oracle.graal.nodes.extended.BranchProbabilityNode.*; -import static org.junit.Assert.*; - import org.junit.*; import com.oracle.graal.nodes.*; -import com.oracle.graal.nodes.calc.*; -import com.oracle.graal.nodes.java.*; -import com.oracle.graal.nodes.java.MethodCallTargetNode.InvokeKind; import com.oracle.graal.nodes.spi.*; import com.oracle.graal.phases.common.*; import com.oracle.graal.phases.tiers.*; /** - * Collection of tests for {@link ConditionalEliminationPhase} including those that triggered bugs - * in this phase. + * Collection of tests for {@link com.oracle.graal.phases.common.ConditionalEliminationPhase} + * including those that triggered bugs in this phase. */ public class ConditionalEliminationTest extends GraalCompilerTest { @@ -88,174 +81,6 @@ } while (true); } - /** - * This test presents a code pattern that triggered a bug where a (non-eliminated) checkcast - * caused an enclosing instanceof (for the same object and target type) to be incorrectly - * eliminated. - */ - @Test - public void testReanchoringIssue() { - Entry end = new Entry("end"); - EntryWithNext e1 = new EntryWithNext("e1", end); - EntryWithNext e2 = new EntryWithNext("e2", e1); - - test("search", e2, "e3", new Entry("e4")); - } - - @SuppressWarnings("unused") - public static int testNullnessSnippet(Object a, Object b) { - if (a == null) { - if (a == b) { - if (b == null) { - return 1; - } else { - return -2; - } - } else { - if (b == null) { - return -3; - } else { - return 4; - } - } - } else { - if (a == b) { - if (b == null) { - return -5; - } else { - return 6; - } - } else { - if (b == null) { - return 7; - } else { - return 8; - } - } - } - } - - @Test - public void testNullness() { - test("testNullnessSnippet", null, null); - test("testNullnessSnippet", null, new Object()); - test("testNullnessSnippet", new Object(), null); - test("testNullnessSnippet", new Object(), new Object()); - - StructuredGraph graph = parse("testNullnessSnippet"); - new ConditionalEliminationPhase(getMetaAccess()).apply(graph); - new CanonicalizerPhase(true).apply(graph, new PhaseContext(getProviders(), null)); - for (ConstantNode constant : getConstantNodes(graph)) { - if (ConstantNodeRecordsUsages || !constant.gatherUsages(graph).isEmpty()) { - assertTrue("unexpected constant: " + constant, constant.asConstant().isNull() || constant.asConstant().asInt() > 0); - } - } - } - - @SuppressWarnings("unused") - public static int testDisjunctionSnippet(Object a) { - try { - if (a instanceof Integer) { - if (a == null) { - return -1; - } else { - return 2; - } - } else { - return 3; - } - } finally { - field = null; - } - } - - @Test - public void testDisjunction() { - StructuredGraph graph = parse("testDisjunctionSnippet"); - new CanonicalizerPhase(true).apply(graph, new PhaseContext(getProviders(), null)); - IfNode ifNode = (IfNode) graph.start().next(); - InstanceOfNode instanceOf = (InstanceOfNode) ifNode.condition(); - IsNullNode x = graph.unique(new IsNullNode(graph.getParameter(0))); - InstanceOfNode y = instanceOf; - ShortCircuitOrNode disjunction = graph.unique(new ShortCircuitOrNode(x, false, y, false, NOT_FREQUENT_PROBABILITY)); - LogicNegationNode negation = graph.unique(new LogicNegationNode(disjunction)); - ifNode.setCondition(negation); - new CanonicalizerPhase(true).apply(graph, new PhaseContext(getProviders(), null)); - new ConditionalEliminationPhase(getMetaAccess()).apply(graph); - new CanonicalizerPhase(true).apply(graph, new PhaseContext(getProviders(), null)); - for (ConstantNode constant : getConstantNodes(graph)) { - if (ConstantNodeRecordsUsages || !constant.gatherUsages(graph).isEmpty()) { - assertTrue("unexpected constant: " + constant, constant.asConstant().isNull() || constant.asConstant().asInt() > 0); - } - } - } - - public static int testInvokeSnippet(Number n) { - if (n instanceof Integer) { - return n.intValue(); - } else { - return 1; - } - } - - @Test - public void testInvoke() { - test("testInvokeSnippet", new Integer(16)); - StructuredGraph graph = parse("testInvokeSnippet"); - new CanonicalizerPhase(true).apply(graph, new PhaseContext(getProviders(), null)); - new ConditionalEliminationPhase(getMetaAccess()).apply(graph); - - InvokeNode invoke = graph.getNodes().filter(InvokeNode.class).first(); - assertEquals(InvokeKind.Special, ((MethodCallTargetNode) invoke.callTarget()).invokeKind()); - } - - public static void testTypeMergingSnippet(Object o, boolean b) { - if (b) { - if (!(o instanceof Double)) { - return; - } - } else { - if (!(o instanceof Integer)) { - return; - } - } - - /* - * For this test the conditional elimination has to correctly merge the type information it - * has about o, so that it can remove the check on Number. - */ - if (!(o instanceof Number)) { - field = o; - } - } - - @Test - public void testTypeMerging() { - StructuredGraph graph = parse("testTypeMergingSnippet"); - new CanonicalizerPhase(true).apply(graph, new PhaseContext(getProviders(), null)); - new ConditionalEliminationPhase(getMetaAccess()).apply(graph); - new CanonicalizerPhase(true).apply(graph, new PhaseContext(getProviders(), null)); - - assertEquals(0, graph.getNodes().filter(StoreFieldNode.class).count()); - } - - public static String testInstanceOfCheckCastSnippet(Object e) { - if (e instanceof Entry) { - return ((Entry) e).name; - } - return null; - } - - @Test - public void testInstanceOfCheckCast() { - StructuredGraph graph = parse("testInstanceOfCheckCastSnippet"); - new CanonicalizerPhase(true).apply(graph, new PhaseContext(getProviders(), null)); - new ConditionalEliminationPhase(getMetaAccess()).apply(graph); - new CanonicalizerPhase(true).apply(graph, new PhaseContext(getProviders(), null)); - - assertEquals(0, graph.getNodes().filter(CheckCastNode.class).count()); - } - public static int testRedundantComparesSnippet(int[] array) { if (array == null) { return 0; @@ -272,39 +97,17 @@ new LoweringPhase(canonicalizer, LoweringTool.StandardLoweringStage.HIGH_TIER).apply(graph, context); canonicalizer.apply(graph, context); new FloatingReadPhase().apply(graph); - new ConditionalEliminationPhase(getMetaAccess()).apply(graph); + new ConditionalEliminationPhase(getMetaAccess()).apply(graph, context); canonicalizer.apply(graph, context); assertEquals(1, graph.getNodes().filter(GuardNode.class).count()); } - public static int testDuplicateNullChecksSnippet(Object a) { - if (a == null) { - return 2; - } - try { - return ((Integer) a).intValue(); - } catch (ClassCastException e) { - return 0; + public static String testInstanceOfCheckCastSnippet(Object e) { + if (e instanceof Entry) { + return ((Entry) e).name; } - } - - @Test - @Ignore - public void testDuplicateNullChecks() { - // This tests whether explicit null checks properly eliminate later null guards. Currently - // it's failing. - StructuredGraph graph = parse("testDuplicateNullChecksSnippet"); - CanonicalizerPhase canonicalizer = new CanonicalizerPhase(true); - PhaseContext context = new PhaseContext(getProviders(), null); - - new LoweringPhase(canonicalizer, LoweringTool.StandardLoweringStage.HIGH_TIER).apply(graph, context); - canonicalizer.apply(graph, context); - new FloatingReadPhase().apply(graph); - new ConditionalEliminationPhase(getMetaAccess()).apply(graph); - canonicalizer.apply(graph, context); - - assertEquals(1, graph.getNodes().filter(GuardNode.class).count()); + return null; } @Test @@ -317,9 +120,10 @@ new LoweringPhase(canonicalizer, LoweringTool.StandardLoweringStage.HIGH_TIER).apply(graph, context); canonicalizer.apply(graph, context); - new ConditionalEliminationPhase(getMetaAccess()).apply(graph); + new ConditionalEliminationPhase(getMetaAccess()).apply(graph, context); canonicalizer.apply(graph, context); assertEquals(0, graph.getNodes().filter(GuardNode.class).count()); } + } diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/FlowSenReduTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/FlowSenReduTest.java Mon Apr 28 11:18:15 2014 +0200 @@ -0,0 +1,395 @@ +/* + * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.graal.compiler.test; + +import com.oracle.graal.debug.Debug; +import com.oracle.graal.debug.DebugConfig; +import com.oracle.graal.debug.DebugConfigScope; +import com.oracle.graal.debug.internal.DebugScope; +import com.oracle.graal.graph.Node; +import com.oracle.graal.nodes.calc.ObjectEqualsNode; +import com.oracle.graal.nodes.util.GraphUtil; +import com.oracle.graal.phases.common.cfs.FlowSensitiveReductionPhase; +import org.junit.*; + +import com.oracle.graal.nodes.*; +import com.oracle.graal.nodes.java.*; +import com.oracle.graal.phases.common.*; +import com.oracle.graal.phases.tiers.*; + +import java.util.Iterator; +import java.util.List; + +/** + * Tests whether {@link com.oracle.graal.phases.common.cfs.FlowSensitiveReductionPhase} actually + * performs some graph rewritings that it's supposed to perform. + */ +public class FlowSenReduTest extends GraalCompilerTest { + + /* + * A previous instanceof makes redundant a follow-up checkcast. + */ + public Object redundantCheckCastSnippet(Number o) { + Integer z = null; + if (o instanceof Integer) { + z = (Integer) o; // this CheckCastNode will be removed + } + return z; + } + + static final Integer i7 = new Integer(7); + + @Test + public void redundantCheckCastTest() { + assertEquals(i7, redundantCheckCastSnippet(i7)); + StructuredGraph result = afterFlowSensitiveReduce("redundantCheckCastSnippet"); + nodeCountEquals(result, CheckCastNode.class, 0); + nodeCountEquals(result, InstanceOfNode.class, 1); + } + + @SuppressWarnings("unused") + public boolean redundantInstanceOfSnippet01(Object o) { + if (o != null) { + Integer x = (Integer) o; + return (o instanceof Number); // this InstanceOfNode will be removed + } + return false; + } + + @Test + public void redundantInstanceOfTest01() { + String snippet = "redundantInstanceOfSnippet01"; + assertEquals(true, redundantInstanceOfSnippet01(i7)); + nodeCountEquals(afterFlowSensitiveReduce(snippet), InstanceOfNode.class, 1); + } + + /* + * The combination of (previous) non-null-check and checkcast make redundant an instanceof. + */ + @SuppressWarnings("unused") + public Object redundantInstanceOfSnippet02(Object o) { + Integer x = (Integer) o; + if (o != null) { + if (o instanceof Number) { // this InstanceOfNode will be removed + return o; + } + } + return null; + } + + @Test + public void redundantInstanceOfTest02() { + String snippet = "redundantInstanceOfSnippet02"; + assertEquals(i7, redundantInstanceOfSnippet02(i7)); + int ioAfter = getNodes(afterFlowSensitiveReduce(snippet), InstanceOfNode.class).size(); + assertEquals(ioAfter, 1); + } + + /* + * Once an exact-type has been inferred (due to instanceof final-class) a callsite is + * devirtualized. + */ + public int devirtualizationSnippet(Object x, Object y) { + boolean c = x instanceof Integer; + if (c && x == y) { + Number z = (Number) y; // this CheckCastNode will be removed + return z.intValue(); // devirtualized into InvokeSpecial on Integer.intValue() + } + return 0; + } + + @Test + public void devirtualizationTest() { + String snippet = "devirtualizationSnippet"; + assertEquals(i7, devirtualizationSnippet(i7, i7)); + nodeCountEquals(afterFlowSensitiveReduce(snippet), CheckCastNode.class, 0); + + StructuredGraph graph = afterFlowSensitiveReduce(snippet); + assertEquals(0, graph.getNodes().filter(CheckCastNode.class).count()); + + List invokeNodes = getNodes(afterFlowSensitiveReduce(snippet), InvokeNode.class); + assertEquals(1, invokeNodes.size()); + + MethodCallTargetNode target = (MethodCallTargetNode) invokeNodes.get(0).callTarget(); + assertEquals(MethodCallTargetNode.InvokeKind.Special, target.invokeKind()); + assertEquals("HotSpotMethod", target.targetMethod().toString()); + } + + /* + * At the return statement, the returned value has been inferred to have type j.l.Number. The + * instanceof is deemed to always evaluate to false. The interplay with tail-duplication is also + * taken into account (resulting in two return statements, each with "false" as input). + */ + @SuppressWarnings("unused") + public boolean t5Snippet(Object o, boolean b) { + Number z; + if (b) { + z = (Number) o; // tail duplication of return stmt, which becomes "return false" + } else { + z = (Integer) o; // tail duplication of return stmt, which becomes "return false" + } + return o instanceof String; // unreachable + } + + @Test + public void t5a() { + String snippet = "t5Snippet"; + assertEquals(false, t5Snippet(null, true)); + StructuredGraph resultGraph = canonicalize(afterFlowSensitiveReduce(snippet)); + nodeCountEquals(resultGraph, ReturnNode.class, 2); + + List returnNodes = getNodes(resultGraph, ReturnNode.class); + Iterator iter = returnNodes.iterator(); + + ConstantNode c1 = (ConstantNode) iter.next().result(); + ConstantNode c2 = (ConstantNode) iter.next().result(); + + assertEquals(c1, c2); + assertEquals(0, c1.getValue().asInt()); + } + + @Test + public void t5b() { + String snippet = "t5Snippet"; + StructuredGraph graph = afterFlowSensitiveReduce(snippet); + canonicalize(graph); + nodeCountEquals(graph, InstanceOfNode.class, 2); + } + + public boolean t6Snippet(Object x, Object y) { + if (!(x instanceof String)) { + return false; + } + if (!(y instanceof Number)) { + return false; + } + return x == y; // two known-not-to-conform reference values can't be == + } + + // TODO: two known-not-to-conform reference values can't be == + // but baseCaseObjectEqualsNode doesn't check that as of now. + public void t6() { + String snippet = "t6Snippet"; + // visualize(snippet); + StructuredGraph graph = afterFlowSensitiveReduce(snippet); + canonicalize(graph); + nodeCountEquals(graph, ObjectEqualsNode.class, 0); + } + + /* + * A previous instanceof check causes a follow-up instanceof to be deemed unsatisfiable, + * resulting in constant-substitution at that usage. + */ + public Object t7Snippet(Object o) { + if (o instanceof Number) { + if (o instanceof String) { // condition amounts to false + return o; // made unreachable + } + } + return null; + } + + @Test + public void t7() { + String snippet = "t7Snippet"; + StructuredGraph graph = afterFlowSensitiveReduce(snippet); + graph = dce(canonicalize(graph)); + // TODO how to simplify IfNode(false) + assertEquals(1, getNodes(graph, InstanceOfNode.class).size()); + + List returnNodes = getNodes(graph, ReturnNode.class); + assertEquals(2, returnNodes.size()); + Iterator iter = returnNodes.iterator(); + + ConstantNode c1 = (ConstantNode) iter.next().result(); + ConstantNode c2 = (ConstantNode) iter.next().result(); + + assertEquals(c1, c2); + Assert.assertTrue(c1.getValue().isNull()); + } + + /* + * During FlowSensitiveReduction, an unreachable branch doesn't contribute to the merged state. + * The resulting ("non-polluted") more precise inferred type after the merge allows + * devirtualizing a callsite. + */ + public int devirtualizationSnippet02(Number o) { + if (o instanceof Integer) { + Number z = o; + if (o instanceof Long) { + z = o; + } + /* + * devirtualized into InvokeSpecial on Integer.intValue() ie the inferred-type is not + * polluted with values from the unreachable branch. + */ + return z.intValue(); + } + return 0; + } + + @Test + public void devirtualizationTest02() { + String snippet = "devirtualizationSnippet02"; + StructuredGraph graph = afterFlowSensitiveReduce(snippet); + + assertEquals(1, getNodes(graph, InvokeNode.class).size()); + + List invokeNodes = getNodes(graph, InvokeNode.class); + assertEquals(1, invokeNodes.size()); + + MethodCallTargetNode target = (MethodCallTargetNode) invokeNodes.get(0).callTarget(); + assertEquals(MethodCallTargetNode.InvokeKind.Special, target.invokeKind()); + assertEquals("HotSpotMethod", target.targetMethod().toString()); + } + + /* + * TODO ClassCastException known to fail --- either Deopt or throw ObjectGetClassNode The latter + * might lead to direct jump to EH if present. + */ + @SuppressWarnings("unused") + public int t9Snippet(Object o) { + try { + if (o instanceof Number) { + String s = (String) o; + /* + * make a long story short: replace the above with throw new ClassCastException (ok, + * actual type of o unknown). + */ + return 1; + } + } catch (ClassCastException e) { + return 2; + } + return 3; + } + + /* + * "Partial evaluation" via canonicalization of an expression (in the last return statement) one + * of whose leaf sub-expressions was determined to be constant. + */ + @SuppressWarnings("unused") + public Object partialEvalSnippet01(Object o, boolean b) { + if (o == null) { + return o; // turned into "return null;" + } else { + Number z; + if (b) { + z = (Number) o; + } else { + z = (Integer) o; + } + return o instanceof String ? this : null; // turned into "return null;" + } + } + + @Test + public void partialEvalTest01() { + String snippet = "partialEvalSnippet01"; + + StructuredGraph graph = afterFlowSensitiveReduce(snippet); + canonicalize(graph); + dce(graph); + + List returnNodes = getNodes(graph, ReturnNode.class); + assertEquals(2, returnNodes.size()); + Iterator iter = returnNodes.iterator(); + + ValueNode c1 = GraphUtil.unproxify(iter.next().result()); + ValueNode c2 = GraphUtil.unproxify(iter.next().result()); + assert !iter.hasNext(); + + Assert.assertTrue(c1.isNullConstant()); + Assert.assertTrue(c2.isNullConstant()); + } + + public static class C { + public int f; + } + + /* + * A previous (assumed successful) instanceof check is reused later on to remove a checkcast. + */ + public void deduplicateInstanceOfSnippet(Object o) { + ((C) o).f = ((C) o).f; // boils down to a single instanceof test + } + + @Test + public void deduplicateInstanceOfTest() { + String snippet = "deduplicateInstanceOfSnippet"; + StructuredGraph graph = afterFlowSensitiveReduce(snippet); + List ioNodes = getNodes(graph, InstanceOfNode.class); + assertEquals(1, ioNodes.size()); + + } + + // --------------------------------------------- + // ----------------- UTILITIES ----------------- + // --------------------------------------------- + + private PhaseContext getPhaseContext() { + return new PhaseContext(getProviders(), null); + } + + private static StructuredGraph dce(StructuredGraph graph) { + new DeadCodeEliminationPhase().apply(graph); + return graph; + } + + private StructuredGraph canonicalize(StructuredGraph graph) { + new CanonicalizerPhase(true).apply(graph, getPhaseContext()); + return graph; + } + + private StructuredGraph flowSensitiveReduce(StructuredGraph graph) { + new FlowSensitiveReductionPhase(getMetaAccess()).apply(graph, getPhaseContext()); + return graph; + } + + public static List getNodes(StructuredGraph graph, Class nodeClass) { + return graph.getNodes().filter(nodeClass).snapshot(); + } + + public void nodeCountEquals(StructuredGraph graph, Class nodeClass, int expected) { + assertEquals(expected, getNodes(graph, nodeClass).size()); + } + + public StructuredGraph afterFlowSensitiveReduce(String snippet) { + StructuredGraph before = canonicalize(parse(snippet)); + // visualize(before, snippet + "-before"); + StructuredGraph result = flowSensitiveReduce(before); + // visualize(result, snippet + "-after"); + return result; + } + + public StructuredGraph visualize(StructuredGraph graph, String title) { + DebugConfig debugConfig = DebugScope.getConfig(); + DebugConfig fixedConfig = Debug.fixedConfig(false, true, false, false, debugConfig.dumpHandlers(), debugConfig.output()); + try (DebugConfigScope s = Debug.setConfig(fixedConfig)) { + Debug.dump(graph, title); + + return graph; + } + } + +} diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/FlowSensitiveReductionTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/FlowSensitiveReductionTest.java Mon Apr 28 11:18:15 2014 +0200 @@ -0,0 +1,293 @@ +/* + * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.graal.compiler.test; + +import static com.oracle.graal.nodes.ConstantNode.*; +import static com.oracle.graal.nodes.extended.BranchProbabilityNode.*; +import static org.junit.Assert.*; + +import com.oracle.graal.phases.common.cfs.FlowSensitiveReductionPhase; +import org.junit.*; + +import com.oracle.graal.nodes.*; +import com.oracle.graal.nodes.calc.*; +import com.oracle.graal.nodes.java.*; +import com.oracle.graal.nodes.java.MethodCallTargetNode.InvokeKind; +import com.oracle.graal.nodes.spi.*; +import com.oracle.graal.phases.common.*; +import com.oracle.graal.phases.tiers.*; + +/** + * Collection of tests for {@link com.oracle.graal.phases.common.cfs.FlowSensitiveReductionPhase} + * including those that triggered bugs in this phase. + */ +public class FlowSensitiveReductionTest extends GraalCompilerTest { + + public static Object field; + + static class Entry { + + final String name; + + public Entry(String name) { + this.name = name; + } + } + + static class EntryWithNext extends Entry { + + public EntryWithNext(String name, Entry next) { + super(name); + this.next = next; + } + + final Entry next; + } + + public static Entry search(Entry start, String name, Entry alternative) { + Entry current = start; + do { + while (current instanceof EntryWithNext) { + if (name != null && current.name == name) { + current = null; + } else { + Entry next = ((EntryWithNext) current).next; + current = next; + } + } + + if (current != null) { + if (current.name.equals(name)) { + return current; + } + } + if (current == alternative) { + return null; + } + current = alternative; + + } while (true); + } + + /** + * This test presents a code pattern that triggered a bug where a (non-eliminated) checkcast + * caused an enclosing instanceof (for the same object and target type) to be incorrectly + * eliminated. + */ + @Test + public void testReanchoringIssue() { + Entry end = new Entry("end"); + EntryWithNext e1 = new EntryWithNext("e1", end); + EntryWithNext e2 = new EntryWithNext("e2", e1); + + test("search", e2, "e3", new Entry("e4")); + } + + @SuppressWarnings("unused") + public static int testNullnessSnippet(Object a, Object b) { + if (a == null) { + if (a == b) { + if (b == null) { + return 1; + } else { + return -2; + } + } else { + if (b == null) { + return -3; + } else { + return 4; + } + } + } else { + if (a == b) { + if (b == null) { + return -5; + } else { + return 6; + } + } else { + if (b == null) { + return 7; + } else { + return 8; + } + } + } + } + + @Test + public void testNullness() { + test("testNullnessSnippet", null, null); + test("testNullnessSnippet", null, new Object()); + test("testNullnessSnippet", new Object(), null); + test("testNullnessSnippet", new Object(), new Object()); + + StructuredGraph graph = parse("testNullnessSnippet"); + PhaseContext context = new PhaseContext(getProviders(), null); + new FlowSensitiveReductionPhase(getMetaAccess()).apply(graph, context); + new CanonicalizerPhase(true).apply(graph, context); + for (ConstantNode constant : getConstantNodes(graph)) { + if (ConstantNodeRecordsUsages || !constant.gatherUsages(graph).isEmpty()) { + assertTrue("unexpected constant: " + constant, constant.asConstant().isNull() || constant.asConstant().asInt() > 0); + } + } + } + + @SuppressWarnings("unused") + public static int testDisjunctionSnippet(Object a) { + try { + if (a instanceof Integer) { + if (a == null) { + return -1; + } else { + return 2; + } + } else { + return 3; + } + } finally { + field = null; + } + } + + @Test + public void testDisjunction() { + StructuredGraph graph = parse("testDisjunctionSnippet"); + new CanonicalizerPhase(true).apply(graph, new PhaseContext(getProviders(), null)); + IfNode ifNode = (IfNode) graph.start().next(); + InstanceOfNode instanceOf = (InstanceOfNode) ifNode.condition(); + IsNullNode x = graph.unique(new IsNullNode(graph.getParameter(0))); + InstanceOfNode y = instanceOf; + ShortCircuitOrNode disjunction = graph.unique(new ShortCircuitOrNode(x, false, y, false, NOT_FREQUENT_PROBABILITY)); + LogicNegationNode negation = graph.unique(new LogicNegationNode(disjunction)); + ifNode.setCondition(negation); + new CanonicalizerPhase(true).apply(graph, new PhaseContext(getProviders(), null)); + new FlowSensitiveReductionPhase(getMetaAccess()).apply(graph, new PhaseContext(getProviders(), null)); + new CanonicalizerPhase(true).apply(graph, new PhaseContext(getProviders(), null)); + for (ConstantNode constant : getConstantNodes(graph)) { + if (ConstantNodeRecordsUsages || !constant.gatherUsages(graph).isEmpty()) { + assertTrue("unexpected constant: " + constant, constant.asConstant().isNull() || constant.asConstant().asInt() > 0); + } + } + } + + public static int testInvokeSnippet(Number n) { + if (n instanceof Integer) { + return n.intValue(); + } else { + return 1; + } + } + + @Test + public void testInvoke() { + test("testInvokeSnippet", new Integer(16)); + StructuredGraph graph = parse("testInvokeSnippet"); + PhaseContext context = new PhaseContext(getProviders(), null); + new CanonicalizerPhase(true).apply(graph, context); + new FlowSensitiveReductionPhase(getMetaAccess()).apply(graph, context); + + InvokeNode invoke = graph.getNodes().filter(InvokeNode.class).first(); + assertEquals(InvokeKind.Special, ((MethodCallTargetNode) invoke.callTarget()).invokeKind()); + } + + public static void testTypeMergingSnippet(Object o, boolean b) { + if (b) { + if (!(o instanceof Double)) { + return; + } + } else { + if (!(o instanceof Integer)) { + return; + } + } + + /* + * For this test the conditional elimination has to correctly merge the type information it + * has about o, so that it can remove the check on Number. + */ + if (!(o instanceof Number)) { + field = o; + } + } + + @Test + public void testTypeMerging() { + StructuredGraph graph = parse("testTypeMergingSnippet"); + PhaseContext context = new PhaseContext(getProviders(), null); + new CanonicalizerPhase(true).apply(graph, context); + new FlowSensitiveReductionPhase(getMetaAccess()).apply(graph, context); + new CanonicalizerPhase(true).apply(graph, new PhaseContext(getProviders(), null)); + + assertEquals(0, graph.getNodes().filter(StoreFieldNode.class).count()); + } + + public static String testInstanceOfCheckCastSnippet(Object e) { + if (e instanceof Entry) { + return ((Entry) e).name; + } + return null; + } + + @Test + public void testInstanceOfCheckCast() { + StructuredGraph graph = parse("testInstanceOfCheckCastSnippet"); + PhaseContext context = new PhaseContext(getProviders(), null); + new CanonicalizerPhase(true).apply(graph, context); + new FlowSensitiveReductionPhase(getMetaAccess()).apply(graph, context); + new CanonicalizerPhase(true).apply(graph, new PhaseContext(getProviders(), null)); + + assertEquals(0, graph.getNodes().filter(CheckCastNode.class).count()); + } + + public static int testDuplicateNullChecksSnippet(Object a) { + if (a == null) { + return 2; + } + try { + return ((Integer) a).intValue(); + } catch (ClassCastException e) { + return 0; + } + } + + @Test + @Ignore + public void testDuplicateNullChecks() { + // This tests whether explicit null checks properly eliminate later null guards. Currently + // it's failing. + StructuredGraph graph = parse("testDuplicateNullChecksSnippet"); + CanonicalizerPhase canonicalizer = new CanonicalizerPhase(true); + PhaseContext context = new PhaseContext(getProviders(), null); + + new LoweringPhase(canonicalizer, LoweringTool.StandardLoweringStage.HIGH_TIER).apply(graph, context); + canonicalizer.apply(graph, context); + new FloatingReadPhase().apply(graph); + new FlowSensitiveReductionPhase(getMetaAccess()).apply(graph, context); + canonicalizer.apply(graph, context); + + assertEquals(1, graph.getNodes().filter(GuardNode.class).count()); + } + +} diff -r 3dde8d8c95b8 -r 40d0022115ee 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 Fri Apr 25 16:21:07 2014 +0200 +++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/GraalCompilerTest.java Mon Apr 28 11:18:15 2014 +0200 @@ -24,8 +24,8 @@ import static com.oracle.graal.api.code.CodeUtil.*; import static com.oracle.graal.compiler.GraalCompiler.*; +import static com.oracle.graal.compiler.common.GraalOptions.*; import static com.oracle.graal.nodes.ConstantNode.*; -import static com.oracle.graal.phases.GraalOptions.*; import java.io.*; import java.lang.reflect.*; @@ -41,6 +41,7 @@ import com.oracle.graal.api.replacements.*; import com.oracle.graal.api.runtime.*; import com.oracle.graal.baseline.*; +import com.oracle.graal.compiler.common.*; import com.oracle.graal.compiler.target.*; import com.oracle.graal.debug.*; import com.oracle.graal.debug.Debug.Scope; @@ -169,7 +170,7 @@ protected void assertEquals(StructuredGraph expected, StructuredGraph graph, boolean excludeVirtual, boolean checkConstants) { String expectedString = getCanonicalGraphString(expected, excludeVirtual, checkConstants); String actualString = getCanonicalGraphString(graph, excludeVirtual, checkConstants); - String mismatchString = "mismatch in graphs:\n========= expected =========\n" + expectedString + "\n\n========= actual =========\n" + actualString; + String mismatchString = "mismatch in graphs:\n========= expected (" + expected + ") =========\n" + expectedString + "\n\n========= actual (" + graph + ") =========\n" + actualString; if (!excludeVirtual && getNodeCountExcludingUnusedConstants(expected) != getNodeCountExcludingUnusedConstants(graph)) { Debug.dump(expected, "Node count not matching - expected"); @@ -675,7 +676,7 @@ } protected InstalledCode addMethod(final ResolvedJavaMethod method, final CompilationResult compResult) { - return getCodeCache().addMethod(method, compResult, null); + return getCodeCache().addMethod(method, compResult, null, null); } /** diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/InfopointReasonTest.java --- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/InfopointReasonTest.java Fri Apr 25 16:21:07 2014 +0200 +++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/InfopointReasonTest.java Mon Apr 28 11:18:15 2014 +0200 @@ -39,7 +39,6 @@ import com.oracle.graal.nodes.*; import com.oracle.graal.phases.*; import com.oracle.graal.phases.tiers.*; -import com.oracle.graal.test.*; /** * Test that infopoints in {@link CompilationResult}s have correctly assigned reasons. @@ -72,7 +71,7 @@ } } - @LongTest + @Test public void lineInfopoints() { final Method method = getMethod("testMethod"); final StructuredGraph graph = parseDebug(method); diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/MemoryScheduleTest.java --- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/MemoryScheduleTest.java Fri Apr 25 16:21:07 2014 +0200 +++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/MemoryScheduleTest.java Mon Apr 28 11:18:15 2014 +0200 @@ -22,7 +22,7 @@ */ package com.oracle.graal.compiler.test; -import static com.oracle.graal.phases.GraalOptions.*; +import static com.oracle.graal.compiler.common.GraalOptions.*; import static org.junit.Assert.*; import java.util.*; diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/NestedLoopTest.java --- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/NestedLoopTest.java Fri Apr 25 16:21:07 2014 +0200 +++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/NestedLoopTest.java Mon Apr 28 11:18:15 2014 +0200 @@ -24,6 +24,7 @@ import org.junit.*; +import com.oracle.graal.compiler.common.cfg.*; import com.oracle.graal.debug.*; import com.oracle.graal.graph.*; import com.oracle.graal.nodes.*; @@ -148,10 +149,10 @@ Debug.dump(graph, "Graph"); ControlFlowGraph cfg = ControlFlowGraph.compute(graph, true, true, true, true); - Assert.assertTrue(cfg.getLoops().length == 3); - Loop rootLoop = cfg.getLoops()[0]; - Loop nestedLoop = cfg.getLoops()[1]; - Loop innerMostLoop = cfg.getLoops()[2]; + Assert.assertTrue(cfg.getLoops().size() == 3); + Loop rootLoop = cfg.getLoops().get(0); + Loop nestedLoop = cfg.getLoops().get(1); + Loop innerMostLoop = cfg.getLoops().get(2); Invoke a = getInvoke("a", graph); Invoke b = getInvoke("b", graph); Invoke c = getInvoke("c", graph); @@ -168,14 +169,14 @@ Debug.dump(graph, "Graph"); } - private static boolean contains(Loop loop, Invoke node, ControlFlowGraph cfg) { + private static boolean contains(Loop loop, Invoke node, ControlFlowGraph cfg) { Block block = cfg.blockFor((Node) node); Assert.assertNotNull(block); return loop.blocks.contains(block); } - private static boolean containsDirect(Loop loop, Invoke node, ControlFlowGraph cfg) { - for (Loop child : loop.children) { + private static boolean containsDirect(Loop loop, Invoke node, ControlFlowGraph cfg) { + for (Loop child : loop.children) { if (contains(child, node, cfg)) { return false; } diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/PushNodesThroughPiTest.java --- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/PushNodesThroughPiTest.java Fri Apr 25 16:21:07 2014 +0200 +++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/PushNodesThroughPiTest.java Mon Apr 28 11:18:15 2014 +0200 @@ -26,6 +26,7 @@ import com.oracle.graal.api.code.*; import com.oracle.graal.api.meta.*; +import com.oracle.graal.compiler.common.type.*; import com.oracle.graal.debug.*; import com.oracle.graal.debug.Debug.Scope; import com.oracle.graal.nodes.*; @@ -71,7 +72,7 @@ for (ReadNode rn : graph.getNodes().filter(ReadNode.class)) { if (rn.location() instanceof ConstantLocationNode && rn.object().stamp() instanceof ObjectStamp) { long disp = ((ConstantLocationNode) rn.location()).getDisplacement(); - ResolvedJavaType receiverType = ObjectStamp.typeOrNull(rn.object()); + ResolvedJavaType receiverType = StampTool.typeOrNull(rn.object()); ResolvedJavaField field = receiverType.findInstanceFieldWithOffset(disp); assert field != null : "Node " + rn + " tries to access a field which doesn't exists for this type"; diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/PushThroughIfTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/PushThroughIfTest.java Mon Apr 28 11:18:15 2014 +0200 @@ -0,0 +1,77 @@ +/* + * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.graal.compiler.test; + +import org.junit.*; + +import com.oracle.graal.api.code.*; +import com.oracle.graal.debug.*; +import com.oracle.graal.nodes.*; +import com.oracle.graal.nodes.util.*; +import com.oracle.graal.phases.common.*; +import com.oracle.graal.phases.tiers.*; + +public class PushThroughIfTest extends GraalCompilerTest { + + public int field1; + public int field2; + + public int testSnippet(boolean b) { + int i; + if (b) { + i = field1; + } else { + i = field1; + } + return i + field2; + } + + @SuppressWarnings("unused") + public int referenceSnippet(boolean b) { + return field1 + field2; + } + + @Test + public void test1() { + test("testSnippet", "referenceSnippet"); + } + + private void test(String snippet, String reference) { + StructuredGraph graph = parse(snippet); + Debug.dump(graph, "Graph"); + for (FrameState fs : graph.getNodes(FrameState.class).snapshot()) { + fs.replaceAtUsages(null); + GraphUtil.killWithUnusedFloatingInputs(fs); + } + new CanonicalizerPhase(true).apply(graph, new PhaseContext(getProviders(), new Assumptions(false))); + new CanonicalizerPhase(true).apply(graph, new PhaseContext(getProviders(), new Assumptions(false))); + + StructuredGraph referenceGraph = parse(reference); + for (FrameState fs : referenceGraph.getNodes(FrameState.class).snapshot()) { + fs.replaceAtUsages(null); + GraphUtil.killWithUnusedFloatingInputs(fs); + } + new CanonicalizerPhase(true).apply(referenceGraph, new PhaseContext(getProviders(), new Assumptions(false))); + assertEquals(referenceGraph, graph); + } +} diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ScalarTypeSystemTest.java --- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ScalarTypeSystemTest.java Fri Apr 25 16:21:07 2014 +0200 +++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ScalarTypeSystemTest.java Mon Apr 28 11:18:15 2014 +0200 @@ -22,6 +22,7 @@ */ package com.oracle.graal.compiler.test; +import com.oracle.graal.phases.common.cfs.FlowSensitiveReductionPhase; import org.junit.*; import com.oracle.graal.api.code.*; @@ -167,8 +168,9 @@ StructuredGraph graph = parse(snippet); Debug.dump(graph, "Graph"); Assumptions assumptions = new Assumptions(false); - new ConditionalEliminationPhase(getMetaAccess()).apply(graph); - new CanonicalizerPhase(true).apply(graph, new PhaseContext(getProviders(), assumptions)); + PhaseContext context = new PhaseContext(getProviders(), assumptions); + new FlowSensitiveReductionPhase(getMetaAccess()).apply(graph, context); + new CanonicalizerPhase(true).apply(graph, context); StructuredGraph referenceGraph = parse(referenceSnippet); assertEquals(referenceGraph, graph); } diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/SimpleCFGTest.java --- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/SimpleCFGTest.java Fri Apr 25 16:21:07 2014 +0200 +++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/SimpleCFGTest.java Mon Apr 28 11:18:15 2014 +0200 @@ -41,9 +41,9 @@ AbstractEndNode trueEnd = graph.add(new EndNode()); AbstractEndNode falseEnd = graph.add(new EndNode()); - AbstractBeginNode trueBegin = graph.add(new BeginNode()); + BeginNode trueBegin = graph.add(new BeginNode()); trueBegin.setNext(trueEnd); - AbstractBeginNode falseBegin = graph.add(new BeginNode()); + BeginNode falseBegin = graph.add(new BeginNode()); falseBegin.setNext(falseEnd); IfNode ifNode = graph.add(new IfNode(null, trueBegin, falseBegin, 0.5)); diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/StampCanonicalizerTest.java --- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/StampCanonicalizerTest.java Fri Apr 25 16:21:07 2014 +0200 +++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/StampCanonicalizerTest.java Mon Apr 28 11:18:15 2014 +0200 @@ -25,8 +25,8 @@ import org.junit.*; import com.oracle.graal.api.code.*; +import com.oracle.graal.compiler.common.type.*; import com.oracle.graal.nodes.*; -import com.oracle.graal.nodes.type.*; import com.oracle.graal.phases.common.*; import com.oracle.graal.phases.tiers.*; diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/TypeSystemTest.java --- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/TypeSystemTest.java Fri Apr 25 16:21:07 2014 +0200 +++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/TypeSystemTest.java Mon Apr 28 11:18:15 2014 +0200 @@ -24,6 +24,7 @@ import java.io.*; +import com.oracle.graal.phases.common.cfs.FlowSensitiveReductionPhase; import org.junit.*; import com.oracle.graal.api.code.*; @@ -184,7 +185,12 @@ StructuredGraph graph = parse(snippet); Debug.dump(graph, "Graph"); Assumptions assumptions = new Assumptions(false); - new ConditionalEliminationPhase(getMetaAccess()).apply(graph); + /* + * When using FlowSensitiveReductionPhase instead of ConditionalEliminationPhase, + * tail-duplication gets activated thus resulting in a graph with more nodes than the + * reference graph. + */ + new ConditionalEliminationPhase(getMetaAccess()).apply(graph, new PhaseContext(getProviders(), assumptions)); new CanonicalizerPhase(true).apply(graph, new PhaseContext(getProviders(), assumptions)); // a second canonicalizer is needed to process nested MaterializeNodes new CanonicalizerPhase(true).apply(graph, new PhaseContext(getProviders(), assumptions)); @@ -239,7 +245,7 @@ StructuredGraph graph = parse(snippet); Assumptions assumptions = new Assumptions(false); new CanonicalizerPhase(true).apply(graph, new PhaseContext(getProviders(), assumptions)); - new ConditionalEliminationPhase(getMetaAccess()).apply(graph); + new FlowSensitiveReductionPhase(getMetaAccess()).apply(graph, new PhaseContext(getProviders(), assumptions)); new CanonicalizerPhase(true).apply(graph, new PhaseContext(getProviders(), assumptions)); Debug.dump(graph, "Graph " + snippet); Assert.assertFalse("shouldn't have nodes of type " + clazz, graph.getNodes().filter(clazz).iterator().hasNext()); diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/backend/AllocatorTest.java --- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/backend/AllocatorTest.java Fri Apr 25 16:21:07 2014 +0200 +++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/backend/AllocatorTest.java Mon Apr 28 11:18:15 2014 +0200 @@ -23,7 +23,7 @@ package com.oracle.graal.compiler.test.backend; import static com.oracle.graal.api.code.CodeUtil.*; -import static com.oracle.graal.phases.GraalOptions.*; +import static com.oracle.graal.compiler.common.GraalOptions.*; import java.util.*; @@ -33,15 +33,15 @@ import com.oracle.graal.api.code.CallingConvention.Type; import com.oracle.graal.api.meta.*; import com.oracle.graal.compiler.*; -import com.oracle.graal.compiler.gen.*; +import com.oracle.graal.compiler.common.cfg.*; import com.oracle.graal.compiler.test.*; import com.oracle.graal.debug.*; import com.oracle.graal.debug.Debug.Scope; import com.oracle.graal.lir.*; import com.oracle.graal.lir.LIRInstruction.ValueProcedure; import com.oracle.graal.lir.StandardOp.MoveOp; +import com.oracle.graal.lir.gen.*; import com.oracle.graal.nodes.*; -import com.oracle.graal.nodes.cfg.*; import com.oracle.graal.phases.*; import com.oracle.graal.phases.schedule.*; diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/deopt/CompiledMethodTest.java --- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/deopt/CompiledMethodTest.java Fri Apr 25 16:21:07 2014 +0200 +++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/deopt/CompiledMethodTest.java Mon Apr 28 11:18:15 2014 +0200 @@ -32,7 +32,6 @@ import com.oracle.graal.nodes.*; import com.oracle.graal.phases.common.*; import com.oracle.graal.phases.tiers.*; -import com.oracle.graal.test.*; /** * In the following tests, the usages of local variable "a" are replaced with the integer constant @@ -51,7 +50,7 @@ return f1 + " " + arg1 + " " + arg2 + " " + arg3; } - @LongTest + @Test public void test1() { Method method = getMethod("testMethod"); final StructuredGraph graph = parse(method); @@ -74,7 +73,7 @@ } } - @LongTest + @Test public void test3() { Method method = getMethod("testMethod"); final StructuredGraph graph = parse(method); @@ -88,7 +87,7 @@ } } - @LongTest + @Test public void test4() { Method method = getMethod("testMethodVirtual"); final StructuredGraph graph = parse(method); diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ea/EscapeAnalysisTest.java --- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ea/EscapeAnalysisTest.java Fri Apr 25 16:21:07 2014 +0200 +++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ea/EscapeAnalysisTest.java Mon Apr 28 11:18:15 2014 +0200 @@ -25,10 +25,10 @@ import org.junit.*; import com.oracle.graal.api.meta.*; +import com.oracle.graal.compiler.common.type.*; import com.oracle.graal.graph.*; import com.oracle.graal.loop.phases.*; import com.oracle.graal.nodes.calc.*; -import com.oracle.graal.nodes.type.*; import com.oracle.graal.nodes.virtual.*; import com.oracle.graal.phases.common.*; import com.oracle.graal.phases.schedule.*; @@ -279,7 +279,7 @@ @SuppressWarnings("unused") public static void testNewNodeSnippet() { - new IntegerAddNode(new IntegerStamp(32, false, Integer.MIN_VALUE, Integer.MAX_VALUE, 0, 0xFFFFFFFF), null, null); + new IntegerAddNode(new IntegerStamp(32, Integer.MIN_VALUE, Integer.MAX_VALUE, 0, 0xFFFFFFFF), null, null); } /** diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ea/PartialEscapeAnalysisTest.java --- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ea/PartialEscapeAnalysisTest.java Fri Apr 25 16:21:07 2014 +0200 +++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ea/PartialEscapeAnalysisTest.java Mon Apr 28 11:18:15 2014 +0200 @@ -120,6 +120,7 @@ } @Test + @Ignore public void testCache() { testPartialEscapeAnalysis("testCacheSnippet", 0.75, 1); } diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ea/UnsafeEATest.java --- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ea/UnsafeEATest.java Fri Apr 25 16:21:07 2014 +0200 +++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ea/UnsafeEATest.java Mon Apr 28 11:18:15 2014 +0200 @@ -27,7 +27,7 @@ import sun.misc.*; import com.oracle.graal.api.meta.*; -import com.oracle.graal.graph.*; +import com.oracle.graal.compiler.common.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.java.*; diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/inlining/InliningTest.java --- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/inlining/InliningTest.java Fri Apr 25 16:21:07 2014 +0200 +++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/inlining/InliningTest.java Mon Apr 28 11:18:15 2014 +0200 @@ -38,7 +38,6 @@ import com.oracle.graal.phases.*; import com.oracle.graal.phases.common.*; import com.oracle.graal.phases.tiers.*; -import com.oracle.graal.test.*; public class InliningTest extends GraalCompilerTest { @@ -73,7 +72,7 @@ assertInlined(getGraph("invokeMethodOnFieldSnippet", false)); } - @LongTest + @Test public void testStaticBindableInliningIP() { assertManyMethodInfopoints(assertInlined(getGraph("invokeConstructorSnippet", true))); assertManyMethodInfopoints(assertInlined(getGraph("invokeFinalMethodSnippet", true))); @@ -82,7 +81,7 @@ } @Ignore("would need read elimination/EA before inlining") - @LongTest + @Test public void testDependentStaticBindableInliningIP() { assertManyMethodInfopoints(assertInlined(getGraph("invokeMethodOnFinalFieldSnippet", true))); assertManyMethodInfopoints(assertInlined(getGraph("invokeMethodOnFieldSnippet", true))); @@ -180,7 +179,7 @@ assertNotInlined(getGraph("invokeOverriddenInterfaceMethodSnippet", false)); } - @LongTest + @Test public void testClassHierarchyAnalysisIP() { assertManyMethodInfopoints(assertInlined(getGraph("invokeLeafClassMethodSnippet", true))); assertManyMethodInfopoints(assertInlined(getGraph("invokeConcreteMethodSnippet", true))); diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/nfi/NativeFunctionInterfaceTest.java --- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/nfi/NativeFunctionInterfaceTest.java Fri Apr 25 16:21:07 2014 +0200 +++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/nfi/NativeFunctionInterfaceTest.java Mon Apr 28 11:18:15 2014 +0200 @@ -22,7 +22,7 @@ */ package com.oracle.graal.compiler.test.nfi; -import static com.oracle.graal.graph.UnsafeAccess.*; +import static com.oracle.graal.compiler.common.UnsafeAccess.*; import static java.io.File.*; import static java.lang.System.*; import static org.junit.Assert.*; diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.compiler/src/META-INF/services/javax.annotation.processing.Processor --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.compiler/src/META-INF/services/javax.annotation.processing.Processor Mon Apr 28 11:18:15 2014 +0200 @@ -0,0 +1,1 @@ +com.oracle.graal.compiler.match.MatchProcessor diff -r 3dde8d8c95b8 -r 40d0022115ee 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 Fri Apr 25 16:21:07 2014 +0200 +++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/GraalCompiler.java Mon Apr 28 11:18:15 2014 +0200 @@ -24,7 +24,7 @@ import static com.oracle.graal.compiler.GraalCompiler.Options.*; import static com.oracle.graal.compiler.MethodFilter.*; -import static com.oracle.graal.phases.GraalOptions.*; +import static com.oracle.graal.compiler.common.GraalOptions.*; import java.util.*; @@ -34,15 +34,17 @@ import com.oracle.graal.api.meta.*; import com.oracle.graal.api.meta.ProfilingInfo.TriState; import com.oracle.graal.compiler.alloc.*; -import com.oracle.graal.compiler.gen.*; +import com.oracle.graal.compiler.common.cfg.*; import com.oracle.graal.compiler.target.*; import com.oracle.graal.debug.*; import com.oracle.graal.debug.Debug.Scope; import com.oracle.graal.debug.internal.*; import com.oracle.graal.lir.*; import com.oracle.graal.lir.asm.*; +import com.oracle.graal.lir.gen.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.cfg.*; +import com.oracle.graal.nodes.spi.*; import com.oracle.graal.nodes.util.*; import com.oracle.graal.options.*; import com.oracle.graal.phases.*; @@ -127,9 +129,8 @@ * * @param graph the graph to be compiled * @param cc the calling convention for calls to the code compiled for {@code graph} - * @param installedCodeOwner the method the compiled code will be - * {@linkplain InstalledCode#getMethod() associated} with once installed. This - * argument can be null. + * @param installedCodeOwner the method the compiled code will be associated with once + * installed. This argument can be null. * @return the result of the compilation */ public static T compileGraph(StructuredGraph graph, Object stub, CallingConvention cc, ResolvedJavaMethod installedCodeOwner, Providers providers, Backend backend, @@ -207,7 +208,7 @@ } } - private static void emitBlock(NodeLIRBuilder nodeLirGen, LIRGenerationResult lirGenRes, Block b, StructuredGraph graph, BlockMap> blockMap) { + private static void emitBlock(NodeLIRBuilderTool nodeLirGen, LIRGenerationResult lirGenRes, Block b, StructuredGraph graph, BlockMap> blockMap) { if (lirGenRes.getLIR().getLIRforBlock(b) == null) { for (Block pred : b.getPredecessors()) { if (!b.isLoopHeader() || !pred.isLoopEnd()) { @@ -245,8 +246,8 @@ try (Scope ds = Debug.scope("BackEnd", lir)) { FrameMap frameMap = backend.newFrameMap(registerConfig); LIRGenerationResult lirGenRes = backend.newLIRGenerationResult(lir, frameMap, stub); - LIRGenerator lirGen = backend.newLIRGenerator(cc, lirGenRes); - NodeLIRBuilder nodeLirGen = backend.newNodeLIRGenerator(graph, lirGen); + LIRGeneratorTool lirGen = backend.newLIRGenerator(cc, lirGenRes); + NodeLIRBuilderTool nodeLirGen = backend.newNodeLIRBuilder(graph, lirGen); try (Scope s = Debug.scope("LIRGen", lirGen)) { for (Block b : linearScanOrder) { diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/alloc/Interval.java --- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/alloc/Interval.java Fri Apr 25 16:21:07 2014 +0200 +++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/alloc/Interval.java Mon Apr 28 11:18:15 2014 +0200 @@ -30,8 +30,8 @@ import com.oracle.graal.api.code.*; import com.oracle.graal.api.meta.*; +import com.oracle.graal.compiler.common.*; import com.oracle.graal.debug.*; -import com.oracle.graal.graph.*; import com.oracle.graal.lir.*; import com.oracle.graal.phases.util.*; diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/alloc/LinearScan.java --- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/alloc/LinearScan.java Fri Apr 25 16:21:07 2014 +0200 +++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/alloc/LinearScan.java Mon Apr 28 11:18:15 2014 +0200 @@ -35,10 +35,11 @@ import com.oracle.graal.compiler.alloc.Interval.RegisterBinding; import com.oracle.graal.compiler.alloc.Interval.RegisterPriority; import com.oracle.graal.compiler.alloc.Interval.SpillState; +import com.oracle.graal.compiler.common.*; +import com.oracle.graal.compiler.common.cfg.*; import com.oracle.graal.compiler.gen.*; import com.oracle.graal.debug.*; import com.oracle.graal.debug.Debug.Scope; -import com.oracle.graal.graph.*; import com.oracle.graal.lir.*; import com.oracle.graal.lir.LIRInstruction.OperandFlag; import com.oracle.graal.lir.LIRInstruction.OperandMode; @@ -46,7 +47,6 @@ import com.oracle.graal.lir.LIRInstruction.ValueProcedure; import com.oracle.graal.lir.StandardOp.MoveOp; import com.oracle.graal.nodes.*; -import com.oracle.graal.nodes.cfg.*; import com.oracle.graal.phases.util.*; /** @@ -335,7 +335,7 @@ } int numLoops() { - return ir.getControlFlowGraph().getLoops().length; + return ir.getControlFlowGraph().getLoops().size(); } boolean isIntervalInLoop(int interval, int loop) { diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/alloc/LinearScanWalker.java --- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/alloc/LinearScanWalker.java Fri Apr 25 16:21:07 2014 +0200 +++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/alloc/LinearScanWalker.java Mon Apr 28 11:18:15 2014 +0200 @@ -34,10 +34,10 @@ import com.oracle.graal.compiler.alloc.Interval.RegisterPriority; import com.oracle.graal.compiler.alloc.Interval.SpillState; import com.oracle.graal.compiler.alloc.Interval.State; +import com.oracle.graal.compiler.common.cfg.*; import com.oracle.graal.debug.*; import com.oracle.graal.lir.*; import com.oracle.graal.lir.StandardOp.MoveOp; -import com.oracle.graal.nodes.cfg.*; import com.oracle.graal.phases.util.*; /** diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/alloc/RegisterVerifier.java --- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/alloc/RegisterVerifier.java Fri Apr 25 16:21:07 2014 +0200 +++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/alloc/RegisterVerifier.java Mon Apr 28 11:18:15 2014 +0200 @@ -28,13 +28,13 @@ import com.oracle.graal.api.code.*; import com.oracle.graal.api.meta.*; +import com.oracle.graal.compiler.common.*; +import com.oracle.graal.compiler.common.cfg.*; import com.oracle.graal.debug.*; -import com.oracle.graal.graph.*; import com.oracle.graal.lir.*; import com.oracle.graal.lir.LIRInstruction.OperandFlag; import com.oracle.graal.lir.LIRInstruction.OperandMode; import com.oracle.graal.lir.LIRInstruction.ValueProcedure; -import com.oracle.graal.nodes.cfg.*; import com.oracle.graal.phases.util.*; /** diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/gen/BytecodeLIRBuilder.java --- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/gen/BytecodeLIRBuilder.java Fri Apr 25 16:21:07 2014 +0200 +++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/gen/BytecodeLIRBuilder.java Mon Apr 28 11:18:15 2014 +0200 @@ -22,16 +22,15 @@ */ package com.oracle.graal.compiler.gen; -import java.lang.reflect.*; - import com.oracle.graal.api.code.*; import com.oracle.graal.api.meta.*; +import com.oracle.graal.lir.gen.*; public class BytecodeLIRBuilder { - protected final LIRGenerator gen; + protected final LIRGeneratorTool gen; protected final BytecodeParserTool parser; - public BytecodeLIRBuilder(LIRGenerator gen, BytecodeParserTool parser) { + public BytecodeLIRBuilder(LIRGeneratorTool gen, BytecodeParserTool parser) { this.gen = gen; this.parser = parser; } @@ -53,7 +52,7 @@ gen.emitIncomingValues(params); Signature sig = method.getSignature(); - boolean isStatic = Modifier.isStatic(method.getModifiers()); + boolean isStatic = method.isStatic(); for (int i = 0; i < sig.getParameterCount(!isStatic); i++) { Value paramValue = params[i]; assert paramValue.getKind() == sig.getParameterKind(i).getStackKind(); diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/gen/DebugInfoBuilder.java --- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/gen/DebugInfoBuilder.java Fri Apr 25 16:21:07 2014 +0200 +++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/gen/DebugInfoBuilder.java Mon Apr 28 11:18:15 2014 +0200 @@ -27,6 +27,7 @@ import com.oracle.graal.api.code.*; import com.oracle.graal.api.meta.*; +import com.oracle.graal.compiler.common.*; import com.oracle.graal.debug.*; import com.oracle.graal.graph.*; import com.oracle.graal.lir.*; @@ -115,21 +116,33 @@ } protected BytecodeFrame computeFrameForState(FrameState state) { - int numLocals = state.localsSize(); - int numStack = state.stackSize(); - int numLocks = state.locksSize(); + try { + assert state.bci != BytecodeFrame.INVALID_FRAMESTATE_BCI; + assert state.bci != BytecodeFrame.UNKNOWN_BCI; + assert state.bci != BytecodeFrame.BEFORE_BCI || state.locksSize() == 0; + assert state.bci != BytecodeFrame.AFTER_BCI || state.locksSize() == 0; + assert state.bci != BytecodeFrame.AFTER_EXCEPTION_BCI || state.locksSize() == 0; + assert !(state.method().isSynchronized() && state.bci != BytecodeFrame.BEFORE_BCI && state.bci != BytecodeFrame.AFTER_BCI && state.bci != BytecodeFrame.AFTER_EXCEPTION_BCI) || + state.locksSize() > 0; + assert state.verify(); + + int numLocals = state.localsSize(); + int numStack = state.stackSize(); + int numLocks = state.locksSize(); - Value[] values = new Value[numLocals + numStack + numLocks]; - computeLocals(state, numLocals, values); - computeStack(state, numLocals, numStack, values); - computeLocks(state, values); + Value[] values = new Value[numLocals + numStack + numLocks]; + computeLocals(state, numLocals, values); + computeStack(state, numLocals, numStack, values); + computeLocks(state, values); - BytecodeFrame caller = null; - if (state.outerFrameState() != null) { - caller = computeFrameForState(state.outerFrameState()); + BytecodeFrame caller = null; + if (state.outerFrameState() != null) { + caller = computeFrameForState(state.outerFrameState()); + } + return new BytecodeFrame(caller, state.method(), state.bci, state.rethrowException(), state.duringCall(), values, numLocals, numStack, numLocks); + } catch (GraalInternalError e) { + throw e.addContext("FrameState: ", state); } - assert state.bci >= FrameState.BEFORE_BCI : "bci == " + state.bci; - return new BytecodeFrame(caller, state.method(), state.bci, state.rethrowException(), state.duringCall(), values, numLocals, numStack, numLocks); } protected void computeLocals(FrameState state, int numLocals, Value[] values) { @@ -168,39 +181,43 @@ private static final DebugMetric STATE_CONSTANTS = Debug.metric("StateConstants"); protected Value toValue(ValueNode value) { - if (value instanceof VirtualObjectNode) { - VirtualObjectNode obj = (VirtualObjectNode) value; - EscapeObjectState state = objectStates.get(obj); - if (state == null && obj.entryCount() > 0) { - // null states occur for objects with 0 fields - throw new GraalInternalError("no mapping found for virtual object %s", obj); - } - if (state instanceof MaterializedObjectState) { - return toValue(((MaterializedObjectState) state).materializedValue()); - } else { - assert obj.entryCount() == 0 || state instanceof VirtualObjectState; - VirtualObject vobject = virtualObjects.get(value); - if (vobject == null) { - vobject = VirtualObject.get(obj.type(), null, virtualObjects.size()); - virtualObjects.put(obj, vobject); + try { + if (value instanceof VirtualObjectNode) { + VirtualObjectNode obj = (VirtualObjectNode) value; + EscapeObjectState state = objectStates.get(obj); + if (state == null && obj.entryCount() > 0) { + // null states occur for objects with 0 fields + throw new GraalInternalError("no mapping found for virtual object %s", obj); } - STATE_VIRTUAL_OBJECTS.increment(); - return vobject; - } - } else if (value instanceof ConstantNode) { - STATE_CONSTANTS.increment(); - return ((ConstantNode) value).getValue(); + if (state instanceof MaterializedObjectState) { + return toValue(((MaterializedObjectState) state).materializedValue()); + } else { + assert obj.entryCount() == 0 || state instanceof VirtualObjectState; + VirtualObject vobject = virtualObjects.get(value); + if (vobject == null) { + vobject = VirtualObject.get(obj.type(), null, virtualObjects.size()); + virtualObjects.put(obj, vobject); + } + STATE_VIRTUAL_OBJECTS.increment(); + return vobject; + } + } else if (value instanceof ConstantNode) { + STATE_CONSTANTS.increment(); + return ((ConstantNode) value).getValue(); - } else if (value != null) { - STATE_VARIABLES.increment(); - Value operand = nodeOperands.get(value); - assert operand != null && (operand instanceof Variable || operand instanceof Constant) : operand + " for " + value; - return operand; + } else if (value != null) { + STATE_VARIABLES.increment(); + Value operand = nodeOperands.get(value); + assert operand != null && (operand instanceof Variable || operand instanceof Constant) : operand + " for " + value; + return operand; - } else { - // return a dummy value because real value not needed - STATE_ILLEGALS.increment(); - return Value.ILLEGAL; + } else { + // return a dummy value because real value not needed + STATE_ILLEGALS.increment(); + return Value.ILLEGAL; + } + } catch (GraalInternalError e) { + throw e.addContext("toValue: ", value); } } } diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/gen/LIRGenerationResult.java --- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/gen/LIRGenerationResult.java Fri Apr 25 16:21:07 2014 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,35 +0,0 @@ -/* - * Copyright (c) 2014, 2014, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -package com.oracle.graal.compiler.gen; - -import com.oracle.graal.lir.*; - -public interface LIRGenerationResult { - FrameMap getFrameMap(); - - LIR getLIR(); - - boolean hasForeignCall(); - - void setForeignCall(boolean b); -} diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/gen/LIRGenerationResultBase.java --- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/gen/LIRGenerationResultBase.java Fri Apr 25 16:21:07 2014 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,59 +0,0 @@ -/* - * Copyright (c) 2014, 2014, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -package com.oracle.graal.compiler.gen; - -import com.oracle.graal.lir.*; - -public class LIRGenerationResultBase implements LIRGenerationResult { - private final LIR lir; - private final FrameMap frameMap; - /** - * Records whether the code being generated makes at least one foreign call. - */ - private boolean hasForeignCall; - - public LIRGenerationResultBase(LIR lir, FrameMap frameMap) { - this.lir = lir; - this.frameMap = frameMap; - } - - public LIR getLIR() { - return lir; - } - - /** - * Determines whether the code being generated makes at least one foreign call. - */ - public boolean hasForeignCall() { - return hasForeignCall; - } - - public final void setForeignCall(boolean hasForeignCall) { - this.hasForeignCall = hasForeignCall; - } - - public final FrameMap getFrameMap() { - return frameMap; - } - -} diff -r 3dde8d8c95b8 -r 40d0022115ee 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 Fri Apr 25 16:21:07 2014 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,637 +0,0 @@ -/* - * Copyright (c) 2009, 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.gen; - -import static com.oracle.graal.api.code.ValueUtil.*; -import static com.oracle.graal.api.meta.Value.*; -import static com.oracle.graal.lir.LIR.*; -import static com.oracle.graal.lir.LIRValueUtil.*; -import static com.oracle.graal.phases.GraalOptions.*; - -import java.util.*; - -import com.oracle.graal.api.code.*; -import com.oracle.graal.api.meta.*; -import com.oracle.graal.asm.*; -import com.oracle.graal.debug.*; -import com.oracle.graal.graph.*; -import com.oracle.graal.lir.*; -import com.oracle.graal.lir.StandardOp.BlockEndOp; -import com.oracle.graal.lir.StandardOp.LabelOp; -import com.oracle.graal.lir.StandardOp.NoOp; -import com.oracle.graal.nodes.*; -import com.oracle.graal.nodes.calc.*; -import com.oracle.graal.nodes.cfg.*; -import com.oracle.graal.nodes.spi.*; -import com.oracle.graal.nodes.type.*; -import com.oracle.graal.options.*; -import com.oracle.graal.phases.util.*; - -/** - * This class traverses the HIR instructions and generates LIR instructions from them. - */ -public abstract class LIRGenerator implements ArithmeticLIRGenerator, LIRGeneratorTool, LIRTypeTool { - - public static class Options { - // @formatter:off - @Option(help = "Print HIR along side LIR as the latter is generated") - public static final OptionValue PrintIRWithLIR = new OptionValue<>(false); - @Option(help = "The trace level for the LIR generator") - public static final OptionValue TraceLIRGeneratorLevel = new OptionValue<>(0); - // @formatter:on - } - - private final Providers providers; - private final CallingConvention cc; - - private DebugInfoBuilder debugInfoBuilder; - - protected AbstractBlock currentBlock; - public final int traceLevel; - public final boolean printIRWithLIR; - - /** - * Handle for an operation that loads a constant into a variable. The operation starts in the - * first block where the constant is used but will eventually be - * {@linkplain LIRGenerator#insertConstantLoads() moved} to a block dominating all usages of the - * constant. - */ - public static class LoadConstant implements Comparable { - /** - * The index of {@link #op} within {@link #block}'s instruction list or -1 if {@code op} is - * to be moved to a dominator block. - */ - int index; - - /** - * The operation that loads the constant. - */ - private final LIRInstruction op; - - /** - * The block that does or will contain {@link #op}. This is initially the block where the - * first usage of the constant is seen during LIR generation. - */ - Block block; - - /** - * The variable into which the constant is loaded. - */ - final Variable variable; - - public LoadConstant(Variable variable, Block block, int index, LIRInstruction op) { - this.variable = variable; - this.block = block; - this.index = index; - this.op = op; - } - - /** - * Sorts {@link LoadConstant} objects according to their enclosing blocks. This is used to - * group loads per block in {@link LIRGenerator#insertConstantLoads()}. - */ - public int compareTo(LoadConstant o) { - if (block.getId() < o.block.getId()) { - return -1; - } - if (block.getId() > o.block.getId()) { - return 1; - } - return 0; - } - - @Override - public String toString() { - return block + "#" + op; - } - - /** - * Removes the {@link #op} from its original location if it is still at that location. - */ - public void unpin(LIR lir) { - if (index >= 0) { - // Replace the move with a filler op so that the operation - // list does not need to be adjusted. - List instructions = lir.getLIRforBlock(block); - instructions.set(index, new NoOp(null, -1)); - index = -1; - } - } - } - - Map constantLoads; - - private LIRGenerationResult res; - - /** - * Set this before using the LIRGenerator. - * - * TODO this should be removed - */ - void setDebugInfoBuilder(DebugInfoBuilder builder) { - debugInfoBuilder = builder; - } - - /** - * Checks whether the supplied constant can be used without loading it into a register for store - * operations, i.e., on the right hand side of a memory access. - * - * @param c The constant to check. - * @return True if the constant can be used directly, false if the constant needs to be in a - * register. - */ - public abstract boolean canStoreConstant(Constant c, boolean isCompressed); - - public LIRGenerator(Providers providers, CallingConvention cc, LIRGenerationResult res) { - this.res = res; - this.providers = providers; - this.cc = cc; - this.traceLevel = Options.TraceLIRGeneratorLevel.getValue(); - this.printIRWithLIR = Options.PrintIRWithLIR.getValue(); - } - - /** - * Returns true if the redundant move elimination optimization should be done after register - * allocation. - */ - public boolean canEliminateRedundantMoves() { - return true; - } - - @Override - public TargetDescription target() { - return getCodeCache().getTarget(); - } - - public Providers getProviders() { - return providers; - } - - @Override - public MetaAccessProvider getMetaAccess() { - return providers.getMetaAccess(); - } - - @Override - public CodeCacheProvider getCodeCache() { - return providers.getCodeCache(); - } - - @Override - public ForeignCallsProvider getForeignCalls() { - return providers.getForeignCalls(); - } - - /** - * Creates a new {@linkplain Variable variable}. - * - * @param platformKind The kind of the new variable. - * @return a new variable - */ - @Override - public Variable newVariable(PlatformKind platformKind) { - return new Variable(platformKind, res.getLIR().nextVariable()); - } - - @Override - public RegisterAttributes attributes(Register register) { - return res.getFrameMap().registerConfig.getAttributesMap()[register.number]; - } - - @Override - public abstract Variable emitMove(Value input); - - public AllocatableValue asAllocatable(Value value) { - if (isAllocatableValue(value)) { - return asAllocatableValue(value); - } else { - return emitMove(value); - } - } - - public Variable load(Value value) { - if (!isVariable(value)) { - return emitMove(value); - } - return (Variable) value; - } - - public Value loadNonConst(Value value) { - if (isConstant(value) && !canInlineConstant((Constant) value)) { - return emitMove(value); - } - return value; - } - - public LabelRef getLIRBlock(FixedNode b) { - assert res.getLIR().getControlFlowGraph() instanceof ControlFlowGraph; - Block result = ((ControlFlowGraph) res.getLIR().getControlFlowGraph()).blockFor(b); - int suxIndex = currentBlock.getSuccessors().indexOf(result); - assert suxIndex != -1 : "Block not in successor list of current block"; - - assert currentBlock instanceof Block; - return LabelRef.forSuccessor(res.getLIR(), currentBlock, suxIndex); - } - - /** - * Determines if only oop maps are required for the code generated from the LIR. - */ - protected boolean needOnlyOopMaps() { - return false; - } - - private static FrameState getFrameState(DeoptimizingNode deopt) { - if (deopt instanceof DeoptimizingNode.DeoptBefore) { - assert !(deopt instanceof DeoptimizingNode.DeoptDuring || deopt instanceof DeoptimizingNode.DeoptAfter); - return ((DeoptimizingNode.DeoptBefore) deopt).stateBefore(); - } else if (deopt instanceof DeoptimizingNode.DeoptDuring) { - assert !(deopt instanceof DeoptimizingNode.DeoptAfter); - return ((DeoptimizingNode.DeoptDuring) deopt).stateDuring(); - } else { - assert deopt instanceof DeoptimizingNode.DeoptAfter; - return ((DeoptimizingNode.DeoptAfter) deopt).stateAfter(); - } - } - - public LIRFrameState state(DeoptimizingNode deopt) { - if (!deopt.canDeoptimize()) { - return null; - } - return stateFor(getFrameState(deopt)); - } - - public LIRFrameState stateWithExceptionEdge(DeoptimizingNode deopt, LabelRef exceptionEdge) { - if (!deopt.canDeoptimize()) { - return null; - } - return stateForWithExceptionEdge(getFrameState(deopt), exceptionEdge); - } - - public LIRFrameState stateFor(FrameState state) { - return stateForWithExceptionEdge(state, null); - } - - public LIRFrameState stateForWithExceptionEdge(FrameState state, LabelRef exceptionEdge) { - if (needOnlyOopMaps()) { - return new LIRFrameState(null, null, null); - } - assert state != null; - return getDebugInfoBuilder().build(state, exceptionEdge); - } - - /** - * Gets the ABI specific operand used to return a value of a given kind from a method. - * - * @param kind the kind of value being returned - * @return the operand representing the ABI defined location used return a value of kind - * {@code kind} - */ - public AllocatableValue resultOperandFor(Kind kind) { - if (kind == Kind.Void) { - return ILLEGAL; - } - return res.getFrameMap().registerConfig.getReturnRegister(kind).asValue(kind); - } - - public void append(LIRInstruction op) { - if (printIRWithLIR && !TTY.isSuppressed()) { - TTY.println(op.toStringWithIdPrefix()); - TTY.println(); - } - assert LIRVerifier.verify(op); - res.getLIR().getLIRforBlock(currentBlock).add(op); - } - - public boolean hasBlockEnd(AbstractBlock block) { - List ops = getResult().getLIR().getLIRforBlock(block); - if (ops.size() == 0) { - return false; - } - return ops.get(ops.size() - 1) instanceof BlockEndOp; - } - - public final void doBlockStart(AbstractBlock block) { - if (printIRWithLIR) { - TTY.print(block.toString()); - } - - currentBlock = block; - - // set up the list of LIR instructions - assert res.getLIR().getLIRforBlock(block) == null : "LIR list already computed for this block"; - res.getLIR().setLIRforBlock(block, new ArrayList()); - - append(new LabelOp(new Label(block.getId()), block.isAligned())); - - if (traceLevel >= 1) { - TTY.println("BEGIN Generating LIR for block B" + block.getId()); - } - } - - public final void doBlockEnd(AbstractBlock block) { - - if (traceLevel >= 1) { - TTY.println("END Generating LIR for block B" + block.getId()); - } - - currentBlock = null; - - if (printIRWithLIR) { - TTY.println(); - } - } - - public void emitIncomingValues(Value[] params) { - ((LabelOp) res.getLIR().getLIRforBlock(currentBlock).get(0)).setIncomingValues(params); - } - - public abstract void emitJump(LabelRef label); - - public abstract void emitCompareBranch(PlatformKind cmpKind, Value left, Value right, Condition cond, boolean unorderedIsTrue, LabelRef trueDestination, LabelRef falseDestination, - double trueDestinationProbability); - - public abstract void emitOverflowCheckBranch(LabelRef overflow, LabelRef noOverflow, double overflowProbability); - - public abstract void emitIntegerTestBranch(Value left, Value right, LabelRef trueDestination, LabelRef falseDestination, double trueSuccessorProbability); - - public abstract Variable emitConditionalMove(PlatformKind cmpKind, Value leftVal, Value right, Condition cond, boolean unorderedIsTrue, Value trueValue, Value falseValue); - - public abstract Variable emitIntegerTestMove(Value leftVal, Value right, Value trueValue, Value falseValue); - - protected abstract void emitForeignCall(ForeignCallLinkage linkage, Value result, Value[] arguments, Value[] temps, LIRFrameState info); - - public static AllocatableValue toStackKind(AllocatableValue value) { - if (value.getKind().getStackKind() != value.getKind()) { - // We only have stack-kinds in the LIR, so convert the operand kind for values from the - // calling convention. - if (isRegister(value)) { - return asRegister(value).asValue(value.getKind().getStackKind()); - } else if (isStackSlot(value)) { - return StackSlot.get(value.getKind().getStackKind(), asStackSlot(value).getRawOffset(), asStackSlot(value).getRawAddFrameSize()); - } else { - throw GraalInternalError.shouldNotReachHere(); - } - } - return value; - } - - @Override - public Variable emitForeignCall(ForeignCallLinkage linkage, DeoptimizingNode info, Value... args) { - LIRFrameState state = null; - if (linkage.canDeoptimize()) { - if (info != null) { - state = stateFor(getFrameState(info)); - } else { - assert needOnlyOopMaps(); - state = new LIRFrameState(null, null, null); - } - } - - // move the arguments into the correct location - CallingConvention linkageCc = linkage.getOutgoingCallingConvention(); - res.getFrameMap().callsMethod(linkageCc); - assert linkageCc.getArgumentCount() == args.length : "argument count mismatch"; - Value[] argLocations = new Value[args.length]; - for (int i = 0; i < args.length; i++) { - Value arg = args[i]; - AllocatableValue loc = linkageCc.getArgument(i); - emitMove(loc, arg); - argLocations[i] = loc; - } - res.setForeignCall(true); - emitForeignCall(linkage, linkageCc.getReturn(), argLocations, linkage.getTemporaries(), state); - - if (isLegal(linkageCc.getReturn())) { - return emitMove(linkageCc.getReturn()); - } else { - return null; - } - } - - protected void emitStrategySwitch(Constant[] keyConstants, double[] keyProbabilities, LabelRef[] keyTargets, LabelRef defaultTarget, Variable value) { - int keyCount = keyConstants.length; - SwitchStrategy strategy = SwitchStrategy.getBestStrategy(keyProbabilities, keyConstants, keyTargets); - long valueRange = keyConstants[keyCount - 1].asLong() - keyConstants[0].asLong() + 1; - double tableSwitchDensity = keyCount / (double) valueRange; - /* - * This heuristic tries to find a compromise between the effort for the best switch strategy - * and the density of a tableswitch. If the effort for the strategy is at least 4, then a - * tableswitch is preferred if better than a certain value that starts at 0.5 and lowers - * gradually with additional effort. - */ - if (strategy.getAverageEffort() < 4 || tableSwitchDensity < (1 / Math.sqrt(strategy.getAverageEffort()))) { - emitStrategySwitch(strategy, value, keyTargets, defaultTarget); - } else { - int minValue = keyConstants[0].asInt(); - assert valueRange < Integer.MAX_VALUE; - LabelRef[] targets = new LabelRef[(int) valueRange]; - for (int i = 0; i < valueRange; i++) { - targets[i] = defaultTarget; - } - for (int i = 0; i < keyCount; i++) { - targets[keyConstants[i].asInt() - minValue] = keyTargets[i]; - } - emitTableSwitch(minValue, defaultTarget, targets, value); - } - } - - protected abstract void emitStrategySwitch(SwitchStrategy strategy, Variable key, LabelRef[] keyTargets, LabelRef defaultTarget); - - protected abstract void emitTableSwitch(int lowKey, LabelRef defaultTarget, LabelRef[] targets, Value key); - - public CallingConvention getCallingConvention() { - return cc; - } - - public DebugInfoBuilder getDebugInfoBuilder() { - assert debugInfoBuilder != null; - return debugInfoBuilder; - } - - @Override - public void beforeRegisterAllocation() { - insertConstantLoads(); - } - - /** - * Moves deferred {@linkplain LoadConstant loads} of constants into blocks dominating all usages - * of the constant. Any operations inserted into a block are guaranteed to be immediately prior - * to the first control flow instruction near the end of the block. - */ - private void insertConstantLoads() { - if (constantLoads != null) { - // Remove loads where all usages are in the same block. - for (Iterator> iter = constantLoads.entrySet().iterator(); iter.hasNext();) { - LoadConstant lc = iter.next().getValue(); - - // Move loads of constant outside of loops - if (OptScheduleOutOfLoops.getValue()) { - Block outOfLoopDominator = lc.block; - while (outOfLoopDominator.getLoop() != null) { - outOfLoopDominator = outOfLoopDominator.getDominator(); - } - if (outOfLoopDominator != lc.block) { - lc.unpin(res.getLIR()); - lc.block = outOfLoopDominator; - } - } - - if (lc.index != -1) { - assert res.getLIR().getLIRforBlock(lc.block).get(lc.index) == lc.op; - iter.remove(); - } - } - if (constantLoads.isEmpty()) { - return; - } - - // Sorting groups the loads per block. - LoadConstant[] groupedByBlock = constantLoads.values().toArray(new LoadConstant[constantLoads.size()]); - Arrays.sort(groupedByBlock); - - int groupBegin = 0; - while (true) { - int groupEnd = groupBegin + 1; - Block block = groupedByBlock[groupBegin].block; - while (groupEnd < groupedByBlock.length && groupedByBlock[groupEnd].block == block) { - groupEnd++; - } - int groupSize = groupEnd - groupBegin; - - List ops = res.getLIR().getLIRforBlock(block); - int lastIndex = ops.size() - 1; - assert ops.get(lastIndex) instanceof BlockEndOp; - int insertionIndex = lastIndex; - for (int i = Math.max(0, lastIndex - MAX_EXCEPTION_EDGE_OP_DISTANCE_FROM_END); i < lastIndex; i++) { - if (getExceptionEdge(ops.get(i)) != null) { - insertionIndex = i; - break; - } - } - - if (groupSize == 1) { - ops.add(insertionIndex, groupedByBlock[groupBegin].op); - } else { - assert groupSize > 1; - List moves = new ArrayList<>(groupSize); - for (int i = groupBegin; i < groupEnd; i++) { - moves.add(groupedByBlock[i].op); - } - ops.addAll(insertionIndex, moves); - } - - if (groupEnd == groupedByBlock.length) { - break; - } - groupBegin = groupEnd; - } - constantLoads = null; - } - } - - /** - * Gets a garbage value for a given kind. - */ - protected Constant zapValueForKind(PlatformKind kind) { - long dead = 0xDEADDEADDEADDEADL; - switch ((Kind) kind) { - case Boolean: - return Constant.FALSE; - case Byte: - return Constant.forByte((byte) dead); - case Char: - return Constant.forChar((char) dead); - case Short: - return Constant.forShort((short) dead); - case Int: - return Constant.forInt((int) dead); - case Double: - return Constant.forDouble(Double.longBitsToDouble(dead)); - case Float: - return Constant.forFloat(Float.intBitsToFloat((int) dead)); - case Long: - return Constant.forLong(dead); - case Object: - return Constant.NULL_OBJECT; - default: - throw new IllegalArgumentException(kind.toString()); - } - } - - /** - * Default implementation: Return the Java stack kind for each stamp. - */ - public PlatformKind getPlatformKind(Stamp stamp) { - return stamp.getPlatformKind(this); - } - - public PlatformKind getIntegerKind(int bits, boolean unsigned) { - if (bits <= 8) { - return Kind.Byte; - } else if (bits <= 16) { - return Kind.Short; - } else if (bits <= 32) { - return Kind.Int; - } else { - assert bits <= 64; - return Kind.Long; - } - } - - public PlatformKind getFloatingKind(int bits) { - switch (bits) { - case 32: - return Kind.Float; - case 64: - return Kind.Double; - default: - throw GraalInternalError.shouldNotReachHere(); - } - } - - public PlatformKind getObjectKind() { - return Kind.Object; - } - - public abstract void emitBitCount(Variable result, Value operand); - - public abstract void emitBitScanForward(Variable result, Value operand); - - public abstract void emitBitScanReverse(Variable result, Value operand); - - public abstract void emitByteSwap(Variable result, Value operand); - - public abstract void emitArrayEquals(Kind kind, Variable result, Value array1, Value array2, Value length); - - public AbstractBlock getCurrentBlock() { - return currentBlock; - } - - void setCurrentBlock(AbstractBlock block) { - currentBlock = block; - } - - public LIRGenerationResult getResult() { - return res; - } -} diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/gen/NodeLIRBuilder.java --- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/gen/NodeLIRBuilder.java Fri Apr 25 16:21:07 2014 +0200 +++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/gen/NodeLIRBuilder.java Mon Apr 28 11:18:15 2014 +0200 @@ -23,6 +23,7 @@ package com.oracle.graal.compiler.gen; import static com.oracle.graal.api.code.ValueUtil.*; +import static com.oracle.graal.compiler.common.GraalOptions.*; import static com.oracle.graal.lir.LIR.*; import static com.oracle.graal.nodes.ConstantNode.*; @@ -31,21 +32,25 @@ import com.oracle.graal.api.code.*; import com.oracle.graal.api.meta.*; -import com.oracle.graal.compiler.gen.LIRGenerator.LoadConstant; -import com.oracle.graal.compiler.target.*; +import com.oracle.graal.compiler.common.*; +import com.oracle.graal.compiler.common.calc.*; +import com.oracle.graal.compiler.common.cfg.*; +import com.oracle.graal.compiler.common.type.*; +import com.oracle.graal.compiler.match.*; import com.oracle.graal.debug.*; import com.oracle.graal.debug.Debug.Scope; import com.oracle.graal.graph.*; import com.oracle.graal.lir.*; import com.oracle.graal.lir.StandardOp.JumpOp; +import com.oracle.graal.lir.gen.*; +import com.oracle.graal.lir.gen.LIRGenerator.LoadConstant; +import com.oracle.graal.lir.gen.LIRGenerator.Options; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.calc.*; import com.oracle.graal.nodes.cfg.*; import com.oracle.graal.nodes.extended.*; import com.oracle.graal.nodes.spi.*; -import com.oracle.graal.nodes.type.*; import com.oracle.graal.nodes.virtual.*; -import com.oracle.graal.phases.*; /** * This class traverses the HIR instructions and generates LIR instructions from them. @@ -55,16 +60,18 @@ private final NodeMap nodeOperands; private final DebugInfoBuilder debugInfoBuilder; - protected final LIRGenerator gen; + protected final LIRGeneratorTool gen; private ValueNode currentInstruction; private ValueNode lastInstructionPrinted; // Debugging only - public NodeLIRBuilder(StructuredGraph graph, LIRGenerator gen) { + private Map, List> matchRules; + + public NodeLIRBuilder(StructuredGraph graph, LIRGeneratorTool gen) { this.gen = gen; this.nodeOperands = graph.createNodeMap(); this.debugInfoBuilder = createDebugInfoBuilder(nodeOperands); - gen.setDebugInfoBuilder(debugInfoBuilder); + matchRules = MatchRuleRegistry.lookup(getClass()); } @SuppressWarnings("hiding") @@ -110,25 +117,25 @@ return setResult(node, value); } else { Variable loadedValue; - if (gen.constantLoads == null) { - gen.constantLoads = new HashMap<>(); + if (gen.getConstantLoads() == null) { + gen.setConstantLoads(new HashMap<>()); } - LoadConstant load = gen.constantLoads.get(value); + LoadConstant load = gen.getConstantLoads().get(value); assert gen.getCurrentBlock() instanceof Block; if (load == null) { int index = gen.getResult().getLIR().getLIRforBlock(gen.getCurrentBlock()).size(); loadedValue = gen.emitMove(value); LIRInstruction op = gen.getResult().getLIR().getLIRforBlock(gen.getCurrentBlock()).get(index); - gen.constantLoads.put(value, new LoadConstant(loadedValue, (Block) gen.getCurrentBlock(), index, op)); + gen.getConstantLoads().put(value, new LoadConstant(loadedValue, gen.getCurrentBlock(), index, op)); } else { - Block dominator = ControlFlowGraph.commonDominator(load.block, (Block) gen.getCurrentBlock()); - loadedValue = load.variable; - if (dominator != load.block) { + AbstractBlock dominator = ControlFlowGraph.commonDominator((Block) load.getBlock(), (Block) gen.getCurrentBlock()); + loadedValue = load.getVariable(); + if (dominator != load.getBlock()) { load.unpin(gen.getResult().getLIR()); } else { - assert load.block != gen.getCurrentBlock() || load.index < gen.getResult().getLIR().getLIRforBlock(gen.getCurrentBlock()).size(); + assert load.getBlock() != gen.getCurrentBlock() || load.getIndex() < gen.getResult().getLIR().getLIRforBlock(gen.getCurrentBlock()).size(); } - load.block = dominator; + load.setBlock(dominator); } return loadedValue; } @@ -151,13 +158,25 @@ @Override public Value setResult(ValueNode x, Value operand) { assert (!isRegister(operand) || !gen.attributes(asRegister(operand)).isAllocatable()); - assert nodeOperands == null || nodeOperands.get(x) == null : "operand cannot be set twice"; + assert nodeOperands != null && (nodeOperands.get(x) == null || nodeOperands.get(x) instanceof ComplexMatchValue) : "operand cannot be set twice"; assert operand != null && isLegal(operand) : "operand must be legal"; assert !(x instanceof VirtualObjectNode); nodeOperands.set(x, operand); return operand; } + /** + * Used by the {@link MatchStatement} machinery to override the generation LIR for some + * ValueNodes. + */ + public void setMatchResult(ValueNode x, Value operand) { + assert operand.equals(Value.INTERIOR_MATCH) || operand instanceof ComplexMatchValue; + assert operand instanceof ComplexMatchValue || x.usages().count() == 1 : "interior matches must be single user"; + assert nodeOperands != null && nodeOperands.get(x) == null : "operand cannot be set twice"; + assert !(x instanceof VirtualObjectNode); + nodeOperands.set(x, operand); + } + public LabelRef getLIRBlock(FixedNode b) { assert gen.getResult().getLIR().getControlFlowGraph() instanceof ControlFlowGraph; Block result = ((ControlFlowGraph) gen.getResult().getLIR().getControlFlowGraph()).blockFor(b); @@ -169,7 +188,7 @@ } public final void append(LIRInstruction op) { - if (gen.printIRWithLIR && !TTY.isSuppressed()) { + if (Options.PrintIRWithLIR.getValue() && !TTY.isSuppressed()) { if (currentInstruction != null && lastInstructionPrinted != currentInstruction) { lastInstructionPrinted = currentInstruction; InstructionPrinter ip = new InstructionPrinter(TTY.out()); @@ -190,10 +209,17 @@ } List nodes = blockMap.get(block); + + if (MatchExpressions.getValue()) { + // Allow NodeLIRBuilder subclass to specialize code generation of any interesting groups + // of instructions + matchComplexExpressions(nodes); + } + int instructionsFolded = 0; for (int i = 0; i < nodes.size(); i++) { Node instr = nodes.get(i); - if (gen.traceLevel >= 3) { + if (Options.TraceLIRGeneratorLevel.getValue() >= 3) { TTY.println("LIRGen for " + instr); } if (instructionsFolded > 0) { @@ -205,19 +231,30 @@ } else if (instr instanceof ValueNode) { ValueNode valueNode = (ValueNode) instr; - if (!hasOperand(valueNode)) { + Value operand = getOperand(valueNode); + if (operand == null) { if (!peephole(valueNode)) { instructionsFolded = maybeFoldMemory(nodes, i, valueNode); if (instructionsFolded == 0) { try { doRoot((ValueNode) instr); } catch (GraalInternalError e) { - throw e.addContext(instr); + throw GraalGraphInternalError.transformAndAddContext(e, instr); } catch (Throwable e) { - throw new GraalInternalError(e).addContext(instr); + throw new GraalGraphInternalError(e).addContext(instr); } } } + } else if (Value.INTERIOR_MATCH.equals(operand)) { + // Doesn't need to be evaluated + Debug.log("interior match for %s", valueNode); + } else if (operand instanceof ComplexMatchValue) { + Debug.log("complex match for %s", valueNode); + ComplexMatchValue match = (ComplexMatchValue) operand; + operand = match.evaluate(this); + if (operand != null) { + setResult(valueNode, operand); + } } else { // There can be cases in which the result of an instruction is already set // before by other instructions. @@ -242,6 +279,31 @@ gen.doBlockEnd(block); } + protected void matchComplexExpressions(List nodes) { + if (matchRules != null) { + try (Scope s = Debug.scope("MatchComplexExpressions")) { + // Match the nodes in backwards order to encourage longer matches. + for (int index = nodes.size() - 1; index >= 0; index--) { + ScheduledNode snode = nodes.get(index); + if (!(snode instanceof ValueNode)) { + continue; + } + ValueNode node = (ValueNode) snode; + // See if this node is the root of any MatchStatements + List statements = matchRules.get(node.getClass()); + if (statements != null) { + for (MatchStatement statement : statements) { + if (statement.generate(this, node, nodes)) { + // Found a match so skip to the next + break; + } + } + } + } + } + } + } + private static final DebugMetric MemoryFoldSuccess = Debug.metric("MemoryFoldSuccess"); private static final DebugMetric MemoryFoldFailed = Debug.metric("MemoryFoldFailed"); private static final DebugMetric MemoryFoldFailedNonAdjacent = Debug.metric("MemoryFoldedFailedNonAdjacent"); @@ -391,7 +453,7 @@ protected abstract boolean peephole(ValueNode valueNode); private void doRoot(ValueNode instr) { - if (gen.traceLevel >= 2) { + if (Options.TraceLIRGeneratorLevel.getValue() >= 2) { TTY.println("Emitting LIR for instruction " + instr); } currentInstruction = instr; @@ -405,14 +467,10 @@ if (Debug.isLogEnabled() && node.stamp() instanceof IllegalStamp) { Debug.log("This node has invalid type, we are emitting dead code(?): %s", node); } - if (node instanceof LIRGenLowerable) { - ((LIRGenLowerable) node).generate(this); - } else if (node instanceof LIRGenResLowerable) { - ((LIRGenResLowerable) node).generate(this, gen.getResult()); - } else if (node instanceof LIRLowerable) { + if (node instanceof LIRLowerable) { ((LIRLowerable) node).generate(this); } else if (node instanceof ArithmeticLIRLowerable) { - ((ArithmeticLIRLowerable) node).generate(this); + ((ArithmeticLIRLowerable) node).generate(this, gen); } else { throw GraalInternalError.shouldNotReachHere("node is not LIRLowerable: " + node); } @@ -458,7 +516,7 @@ } private void moveToPhi(MergeNode merge, AbstractEndNode pred) { - if (gen.traceLevel >= 1) { + if (Options.TraceLIRGeneratorLevel.getValue() >= 1) { TTY.println("MOVE TO PHI from " + pred + " to " + merge); } PhiResolver resolver = new PhiResolver(gen); @@ -566,7 +624,7 @@ if (x instanceof InvokeWithExceptionNode) { exceptionEdge = getLIRBlock(((InvokeWithExceptionNode) x).exceptionEdge()); } - LIRFrameState callState = gen.stateWithExceptionEdge(x, exceptionEdge); + LIRFrameState callState = stateWithExceptionEdge(x, exceptionEdge); Value result = invokeCc.getReturn(); if (callTarget instanceof DirectCallTargetNode) { @@ -659,7 +717,46 @@ return debugInfoBuilder; } - public void emitOverflowCheckBranch(AbstractBeginNode overflowSuccessor, AbstractBeginNode next, double probability) { + private static FrameState getFrameState(DeoptimizingNode deopt) { + if (deopt instanceof DeoptimizingNode.DeoptBefore) { + assert !(deopt instanceof DeoptimizingNode.DeoptDuring || deopt instanceof DeoptimizingNode.DeoptAfter); + return ((DeoptimizingNode.DeoptBefore) deopt).stateBefore(); + } else if (deopt instanceof DeoptimizingNode.DeoptDuring) { + assert !(deopt instanceof DeoptimizingNode.DeoptAfter); + return ((DeoptimizingNode.DeoptDuring) deopt).stateDuring(); + } else { + assert deopt instanceof DeoptimizingNode.DeoptAfter; + return ((DeoptimizingNode.DeoptAfter) deopt).stateAfter(); + } + } + + public LIRFrameState state(DeoptimizingNode deopt) { + if (!deopt.canDeoptimize()) { + return null; + } + return stateFor(getFrameState(deopt)); + } + + public LIRFrameState stateWithExceptionEdge(DeoptimizingNode deopt, LabelRef exceptionEdge) { + if (!deopt.canDeoptimize()) { + return null; + } + return stateForWithExceptionEdge(getFrameState(deopt), exceptionEdge); + } + + public LIRFrameState stateFor(FrameState state) { + return stateForWithExceptionEdge(state, null); + } + + public LIRFrameState stateForWithExceptionEdge(FrameState state, LabelRef exceptionEdge) { + if (gen.needOnlyOopMaps()) { + return new LIRFrameState(null, null, null); + } + assert state != null; + return getDebugInfoBuilder().build(state, exceptionEdge); + } + + public void emitOverflowCheckBranch(BeginNode overflowSuccessor, BeginNode next, double probability) { gen.emitOverflowCheckBranch(getLIRBlock(overflowSuccessor), getLIRBlock(next), probability); } @@ -684,11 +781,7 @@ } @Override - public LIRGenerator getLIRGeneratorTool() { - return gen; - } - - public LIRGenerator getLIRGenerator() { + public LIRGeneratorTool getLIRGeneratorTool() { return gen; } } diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/gen/PhiResolver.java --- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/gen/PhiResolver.java Fri Apr 25 16:21:07 2014 +0200 +++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/gen/PhiResolver.java Mon Apr 28 11:18:15 2014 +0200 @@ -29,22 +29,23 @@ import java.util.*; import com.oracle.graal.api.meta.*; +import com.oracle.graal.lir.gen.*; import com.oracle.graal.nodes.*; /** * Converts {@link ValuePhiNode} instructions into moves. - * + * * Resolves cycles: - * + * *
- * 
+ *
  *  r1 := r2  becomes  temp := r1
  *  r2 := r1           r1 := r2
  *                     r2 := temp
  * 
- * + * * and orders moves: - * + * *
  *  r2 := r3  becomes  r1 := r2
  *  r1 := r2           r2 := r3
@@ -103,7 +104,7 @@
         }
     }
 
-    private final LIRGenerator gen;
+    private final LIRGeneratorTool gen;
 
     /**
      * The operand loop header phi for the operand currently being process in {@link #dispose()}.
@@ -120,7 +121,7 @@
      */
     private final HashMap operandToNodeMap = new HashMap<>();
 
-    public PhiResolver(LIRGenerator gen) {
+    public PhiResolver(LIRGeneratorTool gen) {
         this.gen = gen;
         temp = ILLEGAL;
     }
diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/match/ComplexMatchResult.java
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/match/ComplexMatchResult.java	Mon Apr 28 11:18:15 2014 +0200
@@ -0,0 +1,35 @@
+/*
+ * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.graal.compiler.match;
+
+import com.oracle.graal.api.meta.*;
+import com.oracle.graal.compiler.gen.*;
+
+/*
+ * A closure that can be evaluated to produce the LIR for some complex match. Using a closure
+ * allows normal evaluation in NodeLIRBuilder for all the simple nodes with the complex nodes
+ * evaluated at the proper time.
+ */
+public interface ComplexMatchResult {
+    Value evaluate(NodeLIRBuilder gen);
+}
diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/match/ComplexMatchValue.java
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/match/ComplexMatchValue.java	Mon Apr 28 11:18:15 2014 +0200
@@ -0,0 +1,49 @@
+/*
+ * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.graal.compiler.match;
+
+import com.oracle.graal.api.meta.*;
+import com.oracle.graal.compiler.gen.*;
+
+/**
+ * A wrapper value for the lazy evaluation of a complex match. There's an intermediate class for the
+ * closure because Value is serializable which is a hassle for the little inner classes which
+ * usually occur here.
+ */
+public class ComplexMatchValue extends Value {
+    /**
+     *
+     */
+    private static final long serialVersionUID = -4734670273590368770L;
+
+    final ComplexMatchResult result;
+
+    public ComplexMatchValue(ComplexMatchResult result) {
+        super(Kind.Illegal);
+        this.result = result;
+    }
+
+    public Value evaluate(NodeLIRBuilder builder) {
+        return result.evaluate(builder);
+    }
+}
diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/match/GraalMatchableNodes.java
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/match/GraalMatchableNodes.java	Mon Apr 28 11:18:15 2014 +0200
@@ -0,0 +1,131 @@
+/*
+ * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.graal.compiler.match;
+
+import com.oracle.graal.nodes.*;
+import com.oracle.graal.nodes.calc.*;
+import com.oracle.graal.nodes.extended.*;
+
+/**
+ * Helper class to describe the matchable nodes in the core Graal IR. These could possibly live in
+ * their respective classes but for simplicity in the {@link MatchProcessor} they are grouped here.
+ */
+@MatchableNode(shortName = "Constant", value = ConstantNode.class, inputs = 0)
+@MatchableNode(shortName = "FloatConvert", value = FloatConvertNode.class, inputs = 1, adapter = GraalMatchableNodes.ConvertNodeAdapter.class)
+@MatchableNode(shortName = "FloatSub", value = FloatSubNode.class, inputs = 2, adapter = GraalMatchableNodes.BinaryNodeAdapter.class)
+@MatchableNode(shortName = "FloatingRead", value = FloatingReadNode.class, inputs = 1, adapter = GraalMatchableNodes.ReadNodeAdapter.class)
+@MatchableNode(shortName = "If", value = IfNode.class, inputs = 1, adapter = GraalMatchableNodes.IfNodeAdapter.class)
+@MatchableNode(shortName = "IntegerSub", value = IntegerSubNode.class, inputs = 2, adapter = GraalMatchableNodes.BinaryNodeAdapter.class)
+@MatchableNode(shortName = "LeftShift", value = LeftShiftNode.class, inputs = 2, adapter = GraalMatchableNodes.BinaryNodeAdapter.class)
+@MatchableNode(shortName = "Narrow", value = NarrowNode.class, inputs = 1, adapter = GraalMatchableNodes.ConvertNodeAdapter.class)
+@MatchableNode(shortName = "Read", value = ReadNode.class, inputs = 1, adapter = GraalMatchableNodes.ReadNodeAdapter.class)
+@MatchableNode(shortName = "Reinterpret", value = ReinterpretNode.class, inputs = 1, adapter = GraalMatchableNodes.ReinterpretNodeAdapter.class)
+@MatchableNode(shortName = "SignExtend", value = SignExtendNode.class, inputs = 1, adapter = GraalMatchableNodes.ConvertNodeAdapter.class)
+@MatchableNode(shortName = "UnsignedRightShift", value = UnsignedRightShiftNode.class, inputs = 2, adapter = GraalMatchableNodes.BinaryNodeAdapter.class)
+@MatchableNode(shortName = "Write", value = WriteNode.class, inputs = 2, adapter = GraalMatchableNodes.WriteNodeAdapter.class)
+@MatchableNode(shortName = "ZeroExtend", value = ZeroExtendNode.class, inputs = 1, adapter = GraalMatchableNodes.ConvertNodeAdapter.class)
+@MatchableNode(shortName = "And", value = AndNode.class, inputs = 2, adapter = GraalMatchableNodes.BinaryNodeAdapter.class, commutative = true)
+@MatchableNode(shortName = "FloatAdd", value = FloatAddNode.class, inputs = 2, adapter = GraalMatchableNodes.BinaryNodeAdapter.class, commutative = true)
+@MatchableNode(shortName = "FloatEquals", value = FloatEqualsNode.class, inputs = 2, adapter = GraalMatchableNodes.BinaryOpLogicNodeAdapter.class, commutative = true)
+@MatchableNode(shortName = "FloatLessThan", value = FloatLessThanNode.class, inputs = 2, adapter = GraalMatchableNodes.BinaryOpLogicNodeAdapter.class, commutative = true)
+@MatchableNode(shortName = "FloatMul", value = FloatMulNode.class, inputs = 2, adapter = GraalMatchableNodes.BinaryNodeAdapter.class, commutative = true)
+@MatchableNode(shortName = "IntegerAdd", value = IntegerAddNode.class, inputs = 2, adapter = GraalMatchableNodes.BinaryNodeAdapter.class, commutative = true)
+@MatchableNode(shortName = "IntegerBelowThan", value = IntegerBelowThanNode.class, inputs = 2, adapter = GraalMatchableNodes.BinaryOpLogicNodeAdapter.class, commutative = true)
+@MatchableNode(shortName = "IntegerEquals", value = IntegerEqualsNode.class, inputs = 2, adapter = GraalMatchableNodes.BinaryOpLogicNodeAdapter.class, commutative = true)
+@MatchableNode(shortName = "IntegerLessThan", value = IntegerLessThanNode.class, inputs = 2, adapter = GraalMatchableNodes.BinaryOpLogicNodeAdapter.class, commutative = true)
+@MatchableNode(shortName = "IntegerMul", value = IntegerMulNode.class, inputs = 2, adapter = GraalMatchableNodes.BinaryNodeAdapter.class, commutative = true)
+@MatchableNode(shortName = "IntegerTest", value = IntegerTestNode.class, inputs = 2, adapter = GraalMatchableNodes.BinaryOpLogicNodeAdapter.class, commutative = true)
+@MatchableNode(shortName = "ObjectEquals", value = ObjectEqualsNode.class, inputs = 2, adapter = GraalMatchableNodes.BinaryOpLogicNodeAdapter.class, commutative = true)
+@MatchableNode(shortName = "Or", value = OrNode.class, inputs = 2, adapter = GraalMatchableNodes.BinaryNodeAdapter.class, commutative = true)
+@MatchableNode(shortName = "Xor", value = XorNode.class, inputs = 2, adapter = GraalMatchableNodes.BinaryNodeAdapter.class, commutative = true)
+public class GraalMatchableNodes {
+    public static class BinaryNodeAdapter extends MatchNodeAdapter {
+        @Override
+        protected ValueNode getFirstInput(ValueNode node) {
+            return ((BinaryNode) node).x();
+        }
+
+        @Override
+        protected ValueNode getSecondInput(ValueNode node) {
+            return ((BinaryNode) node).y();
+        }
+    }
+
+    public static class WriteNodeAdapter extends MatchNodeAdapter {
+
+        @Override
+        protected ValueNode getFirstInput(ValueNode node) {
+            return ((WriteNode) node).object();
+        }
+
+        @Override
+        protected ValueNode getSecondInput(ValueNode node) {
+            return ((WriteNode) node).value();
+        }
+    }
+
+    public static class ConvertNodeAdapter extends MatchNodeAdapter {
+
+        @Override
+        protected ValueNode getFirstInput(ValueNode node) {
+            return ((ConvertNode) node).getInput();
+        }
+    }
+
+    public static class ReinterpretNodeAdapter extends MatchNodeAdapter {
+
+        @Override
+        protected ValueNode getFirstInput(ValueNode node) {
+            return ((ReinterpretNode) node).value();
+        }
+    }
+
+    public static class IfNodeAdapter extends MatchNodeAdapter {
+
+        @Override
+        protected ValueNode getFirstInput(ValueNode node) {
+            return ((IfNode) node).condition();
+        }
+    }
+
+    public static class ReadNodeAdapter extends MatchNodeAdapter {
+
+        @Override
+        protected ValueNode getFirstInput(ValueNode node) {
+            return ((Access) node).object();
+        }
+    }
+
+    public static class BinaryOpLogicNodeAdapter extends MatchNodeAdapter {
+
+        @Override
+        protected ValueNode getFirstInput(ValueNode node) {
+            return ((BinaryOpLogicNode) node).x();
+        }
+
+        @Override
+        protected ValueNode getSecondInput(ValueNode node) {
+            return ((BinaryOpLogicNode) node).y();
+        }
+    }
+}
diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/match/MatchContext.java
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/match/MatchContext.java	Mon Apr 28 11:18:15 2014 +0200
@@ -0,0 +1,191 @@
+/*
+ * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.graal.compiler.match;
+
+import java.lang.reflect.*;
+import java.util.*;
+
+import com.oracle.graal.api.meta.*;
+import com.oracle.graal.compiler.common.*;
+import com.oracle.graal.compiler.gen.*;
+import com.oracle.graal.compiler.match.MatchPattern.Result;
+import com.oracle.graal.debug.*;
+import com.oracle.graal.nodes.*;
+import com.oracle.graal.nodes.extended.*;
+import com.oracle.graal.nodes.virtual.*;
+
+/**
+ * Container for state captured during a match.
+ */
+public class MatchContext {
+    private final ArrayList consumed = new ArrayList<>();
+    private final List nodes;
+    private final ValueNode root;
+    private List names;
+    private List> types;
+    private List values;
+    private final MatchStatement rule;
+    private int startIndex;
+    private int endIndex;
+    private final NodeLIRBuilder builder;
+
+    public MatchContext(NodeLIRBuilder builder, MatchStatement rule, ValueNode node, List nodes) {
+        this.builder = builder;
+        this.rule = rule;
+        this.root = node;
+        this.nodes = nodes;
+        // The root should be the last index since all the inputs must be scheduled before.
+        startIndex = endIndex = nodes.indexOf(node);
+    }
+
+    public ValueNode getRoot() {
+        return root;
+    }
+
+    public Result captureNamedValue(String name, Class type, ValueNode value) {
+        if (names == null) {
+            names = new ArrayList<>(2);
+            values = new ArrayList<>(2);
+            types = new ArrayList<>(2);
+        }
+        int index = names.indexOf(name);
+        if (index == -1) {
+            names.add(name);
+            values.add(value);
+            types.add(type);
+            return Result.OK;
+        } else {
+            if (values.get(index) != value) {
+                return Result.NAMED_VALUE_MISMATCH(value, rule.getPattern());
+            }
+            return Result.OK;
+        }
+    }
+
+    public Result validate() {
+        // Ensure that there's no unsafe work in between these operations.
+        for (int i = startIndex; i <= endIndex; i++) {
+            ScheduledNode node = getNodes().get(i);
+            if (node instanceof ConstantNode || node instanceof LocationNode || node instanceof VirtualObjectNode || node instanceof ParameterNode) {
+                // these can be evaluated lazily so don't worry about them. This should probably be
+                // captured by some interface that indicates that their generate method is empty.
+                continue;
+            } else if (!consumed.contains(node) && node != root) {
+                // This is too verbose for normal logging.
+                // Debug.log("unexpected node %s", node);
+                // for (int j = startIndex; j <= endIndex; j++) {
+                // ScheduledNode theNode = getNodes().get(j);
+                // Debug.log("%s(%s) %1s", (consumed.contains(theNode) || theNode == root) ? "*" :
+                // " ",
+                // theNode.usages().count(), theNode);
+                // }
+                return Result.NOT_SAFE(node, rule.getPattern());
+            }
+        }
+        return Result.OK;
+    }
+
+    /**
+     * Transfers the captured value into the MatchGenerator instance. The reflective information
+     * should really be generated and checking during construction of the MatchStatement but this is
+     * ok for now.
+     */
+    public void transferState(MatchGenerator generator) {
+        try {
+            for (int i = 0; i < names.size(); i++) {
+                String name = names.get(i);
+                try {
+                    Field field = generator.getClass().getDeclaredField(name);
+                    field.setAccessible(true);
+                    field.set(generator, values.get(i));
+                } catch (NoSuchFieldException e) {
+                    // Doesn't exist so the generator doesn't care about the value.
+                }
+            }
+        } catch (SecurityException | IllegalArgumentException | IllegalAccessException e) {
+            throw new GraalInternalError(e);
+        }
+        try {
+            Field field = generator.getClass().getDeclaredField("root");
+            field.setAccessible(true);
+            field.set(generator, getRoot());
+        } catch (NoSuchFieldException e) {
+            // Doesn't exist
+        } catch (SecurityException | IllegalAccessException | IllegalArgumentException e) {
+            throw new GraalInternalError(e);
+        }
+    }
+
+    public void setResult(ComplexMatchResult result) {
+        setResult(new ComplexMatchValue(result));
+    }
+
+    /**
+     * Mark the interior nodes with INTERIOR_MATCH and set the Value of the root to be the result.
+     * During final LIR generation it will be evaluated to produce the actual LIR value.
+     *
+     * @param result
+     */
+    public void setResult(ComplexMatchValue result) {
+        Debug.log("matched %s %s", rule.getName(), rule.getPattern());
+        // Debug.log("%s", rule.formatMatch(root));
+        for (ValueNode node : consumed) {
+            // All the interior nodes should be skipped during the normal doRoot calls in
+            // NodeLIRBuilder so mark them as interior matches. The root of the match will get a
+            // closure which will be evaluated to produce the final LIR.
+            getBuilder().setMatchResult(node, Value.INTERIOR_MATCH);
+        }
+        getBuilder().setMatchResult(root, result);
+    }
+
+    /**
+     * Mark a node as consumed by the match. Consumed nodes will never be evaluated.
+     *
+     * @return Result.OK if the node can be safely consumed.
+     */
+    public Result consume(ValueNode node) {
+        if (node.usages().count() != 1) {
+            return Result.TOO_MANY_USERS(node, rule.getPattern());
+        }
+
+        if (getBuilder().hasOperand(node)) {
+            return Result.ALREADY_USED(node, rule.getPattern());
+        }
+
+        int index = getNodes().indexOf(node);
+        if (index == -1) {
+            return Result.NOT_IN_BLOCK(node, rule.getPattern());
+        }
+        startIndex = Math.min(startIndex, index);
+        consumed.add(node);
+        return Result.OK;
+    }
+
+    private NodeLIRBuilder getBuilder() {
+        return builder;
+    }
+
+    private List getNodes() {
+        return nodes;
+    }
+}
diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/match/MatchGenerator.java
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/match/MatchGenerator.java	Mon Apr 28 11:18:15 2014 +0200
@@ -0,0 +1,35 @@
+/*
+ * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.graal.compiler.match;
+
+import com.oracle.graal.compiler.gen.*;
+
+/**
+ * Code generator for complex match patterns.
+ *
+ * @returns null if the match can't be generated or a {@link ComplexMatchResult} that can be
+ *          evaluated during LIR generation to produce the final LIR value.
+ */
+public interface MatchGenerator {
+    ComplexMatchResult match(NodeLIRBuilder gen);
+}
diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/match/MatchNodeAdapter.java
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/match/MatchNodeAdapter.java	Mon Apr 28 11:18:15 2014 +0200
@@ -0,0 +1,42 @@
+/*
+ * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.graal.compiler.match;
+
+import com.oracle.graal.nodes.*;
+
+/**
+ * Helper class to visit the matchable inputs of a node in a specified order. This may not be needed
+ * in the end since this could probably be done using the inputs iterator but it simplifies things
+ * for the moment.
+ */
+public class MatchNodeAdapter {
+    @SuppressWarnings("unused")
+    protected ValueNode getFirstInput(ValueNode node) {
+        throw new InternalError();
+    }
+
+    @SuppressWarnings("unused")
+    protected ValueNode getSecondInput(ValueNode node) {
+        throw new InternalError();
+    }
+}
diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/match/MatchPattern.java
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/match/MatchPattern.java	Mon Apr 28 11:18:15 2014 +0200
@@ -0,0 +1,201 @@
+/*
+ * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.graal.compiler.match;
+
+import com.oracle.graal.graph.Node.Verbosity;
+import com.oracle.graal.nodes.*;
+
+/**
+ * A simple recursive pattern matcher for a DAG of nodes.
+ */
+
+public class MatchPattern {
+
+    enum MatchResultCode {
+        OK,
+        WRONG_CLASS,
+        NAMED_VALUE_MISMATCH,
+        TOO_MANY_USERS,
+        NOT_IN_BLOCK,
+        NOT_SAFE,
+        ALREADY_USED,
+    }
+
+    /**
+     * A descriptive result for match failures. This can be helpful for debugging why a match
+     * doesn't work as expected.
+     */
+    static class Result {
+        final MatchResultCode code;
+        final ScheduledNode node;
+        final MatchPattern matcher;
+
+        Result(MatchResultCode result, ScheduledNode node, MatchPattern matcher) {
+            this.code = result;
+            this.node = node;
+            this.matcher = matcher;
+        }
+
+        static final Result OK = new Result(MatchResultCode.OK, null, null);
+
+        static Result WRONG_CLASS(ValueNode node, MatchPattern matcher) {
+            return new Result(MatchResultCode.WRONG_CLASS, node, matcher);
+        }
+
+        static Result NAMED_VALUE_MISMATCH(ValueNode node, MatchPattern matcher) {
+            return new Result(MatchResultCode.NAMED_VALUE_MISMATCH, node, matcher);
+        }
+
+        static Result TOO_MANY_USERS(ValueNode node, MatchPattern matcher) {
+            return new Result(MatchResultCode.TOO_MANY_USERS, node, matcher);
+        }
+
+        static Result NOT_IN_BLOCK(ScheduledNode node, MatchPattern matcher) {
+            return new Result(MatchResultCode.NOT_IN_BLOCK, node, matcher);
+        }
+
+        static Result NOT_SAFE(ScheduledNode node, MatchPattern matcher) {
+            return new Result(MatchResultCode.NOT_SAFE, node, matcher);
+        }
+
+        static Result ALREADY_USED(ValueNode node, MatchPattern matcher) {
+            return new Result(MatchResultCode.ALREADY_USED, node, matcher);
+        }
+
+        @Override
+        public String toString() {
+            if (code == MatchResultCode.OK) {
+                return "OK";
+            }
+            return code + " " + node.toString(Verbosity.Id) + "|" + node.getClass().getSimpleName() + " " + matcher;
+        }
+    }
+
+    /**
+     * The expected type of the node. It must match exactly.
+     */
+    private final Class nodeClass;
+    /**
+     * An optional name for this node. A name can occur multiple times in a match and that name must
+     * always refer to the same node of the match will fail.
+     */
+    private final String name;
+    /**
+     * An optional pattern for the first input.
+     */
+    private final MatchPattern first;
+    /**
+     * An optional pattern for the second input.
+     */
+    private final MatchPattern second;
+    /**
+     * Helper class to visit the inputs.
+     */
+    private final MatchNodeAdapter adapter;
+    /**
+     * Can there only be one user of the node. Constant nodes can be matched even if there are other
+     * users.
+     */
+    private final boolean singleUser;
+
+    public MatchPattern(String name, boolean singleUser) {
+        this(null, name, null, null, null, singleUser);
+    }
+
+    public MatchPattern(Class nodeClass, String name, boolean singleUser) {
+        this(nodeClass, name, null, null, null, singleUser);
+    }
+
+    public MatchPattern(Class nodeClass, String name, MatchPattern first, MatchNodeAdapter adapter, boolean singleUser) {
+        this(nodeClass, name, first, null, adapter, singleUser);
+    }
+
+    public MatchPattern(Class nodeClass, String name, MatchPattern first, MatchPattern second, MatchNodeAdapter adapter, boolean singleUser) {
+        this.nodeClass = nodeClass;
+        this.name = name;
+        this.singleUser = singleUser;
+        this.first = first;
+        this.second = second;
+        this.adapter = adapter;
+    }
+
+    Class nodeClass() {
+        return nodeClass;
+    }
+
+    Result match(ValueNode node, MatchContext context) {
+        return matchTree(node, context, true);
+    }
+
+    private Result matchTree(ValueNode node, MatchContext context, boolean atRoot) {
+        Result result = Result.OK;
+        if (nodeClass != null && node.getClass() != nodeClass) {
+            return Result.WRONG_CLASS(node, this);
+        }
+        if (singleUser && !atRoot) {
+            result = context.consume(node);
+            if (result != Result.OK) {
+                return result;
+            }
+        }
+
+        if (name != null) {
+            result = context.captureNamedValue(name, nodeClass, node);
+        }
+
+        if (first != null) {
+            result = first.matchTree(adapter.getFirstInput(node), context, false);
+            if (result == Result.OK && second != null) {
+                result = second.matchTree(adapter.getSecondInput(node), context, false);
+            }
+        }
+
+        return result;
+    }
+
+    /**
+     * For a node starting at root, produce a String showing the inputs that matched against this
+     * rule. It's assumed that a match has already succeeded against this rule, otherwise the
+     * printing may produce exceptions.
+     */
+    public String formatMatch(ValueNode root) {
+        String result = String.format("%s", root);
+        if (first == null && second == null) {
+            return result;
+        } else {
+            return "(" + result + (first != null ? " " + first.formatMatch(adapter.getFirstInput(root)) : "") + (second != null ? " " + second.formatMatch(adapter.getSecondInput(root)) : "") + ")";
+        }
+    }
+
+    @Override
+    public String toString() {
+        if (nodeClass == null) {
+            return name;
+        } else {
+            String pre = first != null || second != null ? "(" : "";
+            String post = first != null || second != null ? ")" : "";
+            String nodeName = nodeClass.getSimpleName();
+            return pre + nodeName + (name != null ? "=\"" + name + "\"" : "") + (first != null ? (" " + first.toString()) : "") + (second != null ? (" " + second.toString()) : "") + post;
+        }
+    }
+}
diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/match/MatchProcessor.java
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/match/MatchProcessor.java	Mon Apr 28 11:18:15 2014 +0200
@@ -0,0 +1,574 @@
+/*
+ * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.graal.compiler.match;
+
+import java.io.*;
+import java.util.*;
+import java.util.regex.*;
+
+import javax.annotation.processing.*;
+import javax.lang.model.*;
+import javax.lang.model.element.*;
+import javax.lang.model.type.*;
+import javax.tools.Diagnostic.Kind;
+import javax.tools.*;
+
+import com.oracle.graal.compiler.common.*;
+import com.oracle.graal.compiler.gen.*;
+import com.oracle.graal.nodes.*;
+
+/**
+ * Processes classes annotated with {@link MatchRule}. A {@link MatchStatementSet} service is
+ * generated for each top level class containing at least one such field. These service objects can
+ * be retrieved as follows:
+ *
+ * 
+ *     ServiceLoader sl = ServiceLoader.loadInstalled(MatchStatementSet.class);
+ *     for (MatchStatementSet rules : sl) {
+ *         ...
+ *     }
+ * 
+ */ +@SupportedAnnotationTypes({"com.oracle.graal.compiler.match.MatchRule", "com.oracle.graal.compiler.match.MatchRules", "com.oracle.graal.compiler.match.MatchableNode"}) +public class MatchProcessor extends AbstractProcessor { + + @Override + public SourceVersion getSupportedSourceVersion() { + return SourceVersion.latest(); + } + + private final Set processedMatchRule = new HashSet<>(); + private final Set processedMatchableNode = new HashSet<>(); + + private static class RuleParseError extends RuntimeException { + private static final long serialVersionUID = 6456128283609257490L; + + RuleParseError(String message) { + super(message); + } + } + + private class RuleParser { + final String[] tokens; + int current; + + RuleParser(String rule) { + Matcher m = tokenizer.matcher(rule); + List list = new ArrayList<>(); + int end = 0; + while (m.lookingAt()) { + list.add(m.group(1)); + end = m.end(); + m.region(m.end(), m.regionEnd()); + } + if (end != m.regionEnd()) { + throw new RuleParseError("unexpected tokens :" + rule.substring(m.end(), m.regionEnd())); + } + tokens = list.toArray(new String[0]); + } + + String next() { + return tokens[current++]; + } + + String peek() { + return tokens[current]; + } + + boolean done() { + return current == tokens.length; + } + + private MatchDescriptor parseSexp() { + if (peek().equals("(")) { + next(); + MatchDescriptor descriptor = parseType(true); + for (int n = 0; n < descriptor.nodeType.inputs; n++) { + if (peek().equals("(")) { + descriptor.inputs[n] = parseSexp(); + } else { + descriptor.inputs[n] = parseType(false); + } + } + for (int n = 0; n < descriptor.nodeType.inputs; n++) { + if (descriptor.inputs[n] == null) { + throw new RuleParseError("not enough inputs for " + descriptor.name); + } + } + if (peek().equals(")")) { + next(); + return descriptor; + } + } + throw new RuleParseError("didn't swallow sexp at: " + peek()); + } + + private MatchDescriptor parseType(boolean sexp) { + TypeDescriptor type = null; + String name = null; + if (Character.isUpperCase(peek().charAt(0))) { + String token = next(); + type = types.get(token); + if (type == null) { + throw new RuleParseError("unknown node type: " + token); + } + if (peek().equals("=")) { + next(); + name = next(); + } + } else { + name = next(); + type = null; + } + return new MatchDescriptor(type, name, sexp); + } + + ArrayList generateVariants() { + MatchDescriptor descriptor = parseSexp(); + if (!done()) { + throw new RuleParseError("didn't consume all tokens"); + } + return descriptor.generateVariants(); + } + } + + static Pattern tokenizer = Pattern.compile("\\s*([()=]|[A-Za-z][A-Za-z0-9]*)\\s*"); + + static class TypeDescriptor { + /** + * The name uses in match expressions to refer to this type. + */ + final String shortName; + /** + * The {@link ValueNode} class represented by this type. + */ + final String nodeClass; + + /** + * The {@link ValueNode} class represented by this type. + */ + final String nodePackage; + + /** + * Expected number of matchable inputs. Should be less <= 2 at the moment. + */ + final int inputs; + + /** + * An adapter class to read the proper matchable inputs of the class. + */ + final String adapter; + + /** + * Should swapped variants of this match be generated. The user of the match is expected to + * compensate for any ordering differences in compare which are commutative but require + * reinterpreting the condition in that case. + */ + final boolean commutative; + + /** + * Can multiple users of this node subsume it. Constants can be swallowed into a match even + * if there are multiple users. + */ + final boolean cloneable; + + TypeDescriptor(String shortName, String nodeClass, String nodePackage, int inputs, String adapter, boolean commutative) { + this.shortName = shortName; + this.nodeClass = nodeClass; + this.nodePackage = nodePackage; + this.inputs = inputs; + this.adapter = adapter; + this.commutative = commutative; + this.cloneable = (nodePackage + "." + nodeClass).equals(ConstantNode.class.getName()); + assert !commutative || inputs == 2; + } + } + + HashMap types = new HashMap<>(); + ArrayList packages = new ArrayList<>(); + + private void declareType(String shortName, String nodeClass, String nodePackage, int inputs, String adapter, boolean commutative) { + TypeDescriptor descriptor = new TypeDescriptor(shortName, nodeClass, nodePackage, inputs, adapter, commutative); + types.put(shortName, descriptor); + if (!packages.contains(descriptor.nodePackage)) { + packages.add(descriptor.nodePackage); + } + } + + private static String findPackage(Element type) { + Element enclosing = type.getEnclosingElement(); + while (enclosing != null && enclosing.getKind() != ElementKind.PACKAGE) { + enclosing = enclosing.getEnclosingElement(); + } + if (enclosing != null && enclosing.getKind() == ElementKind.PACKAGE) { + return ((PackageElement) enclosing).getQualifiedName().toString(); + } + throw new GraalInternalError("can't find package for %s", type); + } + + static class MatchDescriptor { + TypeDescriptor nodeType; + String name; + MatchDescriptor[] inputs; + + MatchDescriptor(TypeDescriptor nodeType, String name, boolean sexp) { + this.nodeType = nodeType; + this.name = name; + if (sexp) { + this.inputs = new MatchDescriptor[nodeType.inputs]; + } else { + this.inputs = new MatchDescriptor[0]; + } + } + + ArrayList generateVariants() { + String prefix = formatPrefix(); + String suffix = formatSuffix(); + ArrayList variants = new ArrayList<>(); + if (inputs.length == 2) { + // Generate this version and a swapped version + for (String first : inputs[0].generateVariants()) { + for (String second : inputs[1].generateVariants()) { + variants.add(prefix + ", " + first + ", " + second + suffix); + if (nodeType.commutative) { + variants.add(prefix + ", " + second + ", " + first + suffix); + } + } + } + } else if (inputs.length == 1) { + for (String first : inputs[0].generateVariants()) { + variants.add(prefix + ", " + first + suffix); + } + } else { + variants.add(prefix + suffix); + } + return variants; + } + + private String formatPrefix() { + if (nodeType == null) { + return String.format("new MatchPattern(%s, false", name != null ? ("\"" + name + "\"") : "null"); + } else { + return String.format("new MatchPattern(%s.class, %s", nodeType.nodeClass, name != null ? ("\"" + name + "\"") : "null"); + } + } + + private String formatSuffix() { + if (nodeType != null) { + if (inputs.length != nodeType.inputs) { + return ", true)"; + } else { + if (nodeType.adapter != null) { + return ", " + nodeType.adapter + "," + !nodeType.cloneable + ")"; + } + if (nodeType.cloneable) { + return ", false)"; + } + } + } + return ")"; + } + + } + + private void createFiles(MatchRuleDescriptor info) { + String pkg = ((PackageElement) info.topDeclaringType.getEnclosingElement()).getQualifiedName().toString(); + Name topDeclaringClass = info.topDeclaringType.getSimpleName(); + + String optionsClassName = topDeclaringClass + "_" + MatchStatementSet.class.getSimpleName(); + Element[] originatingElements = info.originatingElements.toArray(new Element[info.originatingElements.size()]); + + Filer filer = processingEnv.getFiler(); + try (PrintWriter out = createSourceFile(pkg, optionsClassName, filer, originatingElements)) { + + out.println("// CheckStyle: stop header check"); + out.println("// GENERATED CONTENT - DO NOT EDIT"); + out.println("// Source: " + topDeclaringClass + ".java"); + out.println("package " + pkg + ";"); + out.println(""); + out.println("import java.util.*;"); + out.println("import " + MatchStatementSet.class.getPackage().getName() + ".*;"); + out.println("import " + NodeLIRBuilder.class.getName() + ";"); + for (String p : packages) { + out.println("import " + p + ".*;"); + } + out.println(""); + out.println("public class " + optionsClassName + " implements " + MatchStatementSet.class.getSimpleName() + " {"); + String desc = MatchStatement.class.getSimpleName(); + out.println(" // CheckStyle: stop line length check"); + out.println(" private static final List<" + desc + "> options = Collections.unmodifiableList(Arrays.asList("); + + int i = 0; + for (MatchRuleItem option : info.options) { + String optionValue; + if (option.field.getModifiers().contains(Modifier.PRIVATE)) { + optionValue = "field(" + option.declaringClass + ".class, \"" + option.field.getSimpleName() + "\")"; + } else { + optionValue = option.declaringClass + "." + option.field.getSimpleName(); + } + String name = option.name; + Name fieldName = option.field.getSimpleName(); + String comma = i == info.options.size() - 1 ? "" : ","; + out.printf(" new MatchStatement(\"%s\", %s, %s.class)%s\n", fieldName, name, optionValue, comma); + i++; + } + out.println(" ));"); + out.println(" // CheckStyle: resume line length check"); + out.println(); + + out.println(" public Class forClass() {"); + out.println(" return " + topDeclaringClass + ".class;"); + out.println(" }"); + out.println(); + out.println(" @Override"); + out.println(" public List<" + desc + "> statements() {"); + out.println(" return options;"); + out.println(" }"); + out.println("}"); + } + + try { + createProviderFile(pkg, optionsClassName, originatingElements); + } catch (IOException e) { + processingEnv.getMessager().printMessage(Kind.ERROR, e.getMessage(), info.topDeclaringType); + } + } + + private void createProviderFile(String pkg, String providerClassName, Element... originatingElements) throws IOException { + String filename = "META-INF/providers/" + pkg + "." + providerClassName; + FileObject file = processingEnv.getFiler().createResource(StandardLocation.CLASS_OUTPUT, "", filename, originatingElements); + PrintWriter writer = new PrintWriter(new OutputStreamWriter(file.openOutputStream(), "UTF-8")); + writer.println(MatchStatementSet.class.getName()); + writer.close(); + } + + protected PrintWriter createSourceFile(String pkg, String relativeName, Filer filer, Element... originatingElements) { + try { + // Ensure Unix line endings to comply with Graal code style guide checked by Checkstyle + JavaFileObject sourceFile = filer.createSourceFile(pkg + "." + relativeName, originatingElements); + return new PrintWriter(sourceFile.openWriter()) { + + @Override + public void println() { + print("\n"); + } + }; + } catch (IOException e) { + throw new RuntimeException(e); + } + } + + static class MatchRuleItem implements Comparable { + + final String name; + final String declaringClass; + final TypeElement field; + + public MatchRuleItem(String name, String declaringClass, TypeElement field) { + this.name = name; + this.declaringClass = declaringClass; + this.field = field; + } + + @Override + public int compareTo(MatchRuleItem other) { + return name.compareTo(other.name); + } + + @Override + public String toString() { + return declaringClass + "." + field; + } + } + + static class MatchRuleDescriptor { + + final TypeElement topDeclaringType; + final List options = new ArrayList<>(); + final Set originatingElements = new HashSet<>(); + + public MatchRuleDescriptor(TypeElement topDeclaringType) { + this.topDeclaringType = topDeclaringType; + } + } + + private static TypeElement topDeclaringType(Element element) { + Element enclosing = element.getEnclosingElement(); + if (enclosing == null || enclosing.getKind() == ElementKind.PACKAGE) { + assert element.getKind() == ElementKind.CLASS || element.getKind() == ElementKind.INTERFACE; + return (TypeElement) element; + } + return topDeclaringType(enclosing); + } + + @Override + public boolean process(Set annotations, RoundEnvironment roundEnv) { + if (roundEnv.processingOver()) { + return true; + } + + try { + // Import default definitions + processMatchableNode(processingEnv.getElementUtils().getTypeElement(GraalMatchableNodes.class.getName())); + for (Element element : roundEnv.getElementsAnnotatedWith(MatchableNodeImport.class)) { + // Import any other definitions required by this element + String[] imports = element.getAnnotation(MatchableNodeImport.class).value(); + for (String m : imports) { + TypeElement el = processingEnv.getElementUtils().getTypeElement(m); + processMatchableNode(el); + } + } + + // Process any local MatchableNode declarations + for (Element element : roundEnv.getElementsAnnotatedWith(MatchableNode.class)) { + processMatchableNode(element); + } + + Map map = new HashMap<>(); + for (Element element : roundEnv.getElementsAnnotatedWith(MatchRule.class)) { + processMatchRule(map, element); + } + for (Element element : roundEnv.getElementsAnnotatedWith(MatchRules.class)) { + processMatchRule(map, element); + } + + for (MatchRuleDescriptor info : map.values()) { + createFiles(info); + } + + } catch (Throwable t) { + processingEnv.getMessager().printMessage(Kind.ERROR, "Exception throw during processing: " + t); + } + + return true; + } + + /** + * Build up the type table to be used during parsing of the MatchRule. + */ + private void processMatchableNode(Element element) { + if (!processedMatchableNode.contains(element)) { + processedMatchableNode.add(element); + TypeElement topDeclaringType = topDeclaringType(element); + MatchableNode[] matchables = element.getAnnotationsByType(MatchableNode.class); + for (MatchableNode matchable : matchables) { + String nodeClass; + String nodePackage; + String shortName = matchable.shortName(); + TypeMirror nodeClassMirror = null; + try { + matchable.value(); + } catch (MirroredTypeException e) { + nodeClassMirror = e.getTypeMirror(); + } + if (nodeClassMirror == null) { + throw new GraalInternalError("Can't get mirror for node class %s", element); + } + if (nodeClassMirror.toString().equals(MatchableNode.class.getName())) { + nodeClass = topDeclaringType.getQualifiedName().toString(); + } else { + nodeClass = nodeClassMirror.toString(); + } + nodePackage = findPackage(processingEnv.getElementUtils().getTypeElement(nodeClass)); + assert nodeClass.startsWith(nodePackage); + nodeClass = nodeClass.substring(nodePackage.length() + 1); + + TypeMirror nodeAdapterMirror = null; + try { + matchable.adapter(); + } catch (MirroredTypeException e) { + nodeAdapterMirror = e.getTypeMirror(); + } + if (nodeAdapterMirror == null) { + throw new GraalInternalError("Can't get mirror for adapter %s", element); + } + String nodeAdapter = null; + if (!nodeAdapterMirror.toString().equals(MatchableNode.class.getName())) { + nodeAdapter = String.format("new %s()", nodeAdapterMirror.toString()); + } + + declareType(shortName, nodeClass, nodePackage, matchable.inputs(), nodeAdapter, matchable.commutative()); + } + } + } + + private void processMatchRule(Map map, Element element) { + if (!processedMatchRule.contains(element)) { + processedMatchRule.add(element); + TypeElement topDeclaringType = topDeclaringType(element); + MatchRuleDescriptor options = map.get(topDeclaringType); + if (options == null) { + options = new MatchRuleDescriptor(topDeclaringType); + map.put(topDeclaringType, options); + } + MatchRule[] matchRules = element.getAnnotationsByType(MatchRule.class); + for (MatchRule matchRule : matchRules) { + processMatchRule(element, options, matchRule); + } + } + } + + private void processMatchRule(Element element, MatchRuleDescriptor info, MatchRule matchRule) { + assert element instanceof TypeElement; + assert element.getKind() == ElementKind.CLASS; + TypeElement field = (TypeElement) element; + + TypeMirror fieldType = field.asType(); + if (fieldType.getKind() != TypeKind.DECLARED) { + processingEnv.getMessager().printMessage(Kind.ERROR, "Option field must be of type " + MatchRule.class.getName(), element); + return; + } + + Element enclosing = element.getEnclosingElement(); + String declaringClass = ""; + String separator = ""; + Set originatingElementsList = info.originatingElements; + originatingElementsList.add(field); + while (enclosing != null) { + if (enclosing.getKind() == ElementKind.CLASS || enclosing.getKind() == ElementKind.INTERFACE) { + if (enclosing.getModifiers().contains(Modifier.PRIVATE)) { + String msg = String.format("Option field cannot be declared in a private %s %s", enclosing.getKind().name().toLowerCase(), enclosing); + processingEnv.getMessager().printMessage(Kind.ERROR, msg, element); + return; + } + originatingElementsList.add(enclosing); + declaringClass = enclosing.getSimpleName() + separator + declaringClass; + separator = "."; + } else { + assert enclosing.getKind() == ElementKind.PACKAGE; + } + enclosing = enclosing.getEnclosingElement(); + } + + String rule = matchRule.value(); + try { + ArrayList matches = new RuleParser(rule).generateVariants(); + for (String match : matches) { + info.options.add(new MatchRuleItem(match, declaringClass, field)); + } + } catch (RuleParseError e) { + processingEnv.getMessager().printMessage(Kind.ERROR, e.getMessage(), element); + } + } + +} diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/match/MatchRule.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/match/MatchRule.java Mon Apr 28 11:18:15 2014 +0200 @@ -0,0 +1,50 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.graal.compiler.match; + +import java.lang.annotation.*; + +import com.oracle.graal.nodes.*; + +/** + * This annotation declares a textual pattern for matching an HIR DAG. It's an s-expression with a + * node followed by its inputs. Node types are always uppercase and lowercase words are the names of + * nodes. + * + *
+ *   NAME := [a-z][a-zA-Z0-9]*
+ *   NODETYPE := [A-Z][a-zA-Z0-9]*
+ *   NODEORNAME :=  NODE [ = NAME ] | NAME
+ *   EXPRESSION := ( NODEORNAME [ EXPRESSION | NODEORNAME [ EXPRESSION | NODEORNAME ] )
+ * 
+ * + * All matched nodes except the root of the match and {@link ConstantNode}s must have a single user. + * All matched nodes must be in the same block. + */ + +@Retention(RetentionPolicy.RUNTIME) +@Target(ElementType.TYPE) +@Repeatable(value = MatchRules.class) +public @interface MatchRule { + String value(); +} diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/match/MatchRuleRegistry.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/match/MatchRuleRegistry.java Mon Apr 28 11:18:15 2014 +0200 @@ -0,0 +1,79 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.graal.compiler.match; + +import java.util.*; + +import com.oracle.graal.compiler.gen.*; +import com.oracle.graal.nodes.*; + +public class MatchRuleRegistry { + + private static final HashMap, Map, List>> registry = new HashMap<>(); + + /** + * Collect all the {@link MatchStatement}s defined by the superclass chain of theClass. + * + * @param theClass + * @return the set of {@link MatchStatement}s applicable to theClass. + */ + public synchronized static Map, List> lookup(Class theClass) { + Map, List> result = registry.get(theClass); + + if (result == null) { + HashMap, List> localRules = new HashMap<>(); + ServiceLoader sl = ServiceLoader.loadInstalled(MatchStatementSet.class); + for (MatchStatementSet rules : sl) { + localRules.put(rules.forClass(), rules.statements()); + } + + // Walk the class hierarchy collecting lists and merge them together. The subclass + // rules are first which gives them preference over earlier rules. + Map, List> rules = new HashMap<>(); + Class currentClass = theClass; + do { + List statements = localRules.get(currentClass); + if (statements != null) { + for (MatchStatement statement : statements) { + Class nodeClass = statement.getPattern().nodeClass(); + List current = rules.get(nodeClass); + if (current == null) { + current = new ArrayList<>(); + rules.put(nodeClass, current); + } + current.add(statement); + } + } + currentClass = currentClass.getSuperclass(); + } while (currentClass != NodeLIRBuilder.class); + registry.put(theClass, rules); + assert registry.get(theClass) == rules; + result = rules; + } + + if (result.size() == 0) { + return null; + } + return result; + } +} diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/match/MatchRules.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/match/MatchRules.java Mon Apr 28 11:18:15 2014 +0200 @@ -0,0 +1,34 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.graal.compiler.match; + +import java.lang.annotation.*; + +/** + * The repeatable representation of {@link MatchRule}. Should never be used directly. + */ +@Retention(RetentionPolicy.RUNTIME) +@Target(ElementType.TYPE) +public @interface MatchRules { + MatchRule[] value(); +} diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/match/MatchStatement.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/match/MatchStatement.java Mon Apr 28 11:18:15 2014 +0200 @@ -0,0 +1,106 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.graal.compiler.match; + +import java.util.*; + +import com.oracle.graal.api.meta.*; +import com.oracle.graal.compiler.common.*; +import com.oracle.graal.compiler.gen.*; +import com.oracle.graal.compiler.match.MatchPattern.Result; +import com.oracle.graal.nodes.*; + +/** + * A named {@link MatchPattern} along with a {@link MatchGenerator} that can be evaluated to replace + * one or more {@link ValueNode}s with a single {@link Value}. + */ + +public class MatchStatement { + private final String name; + private final MatchPattern pattern; + private final Class generatorClass; + + public MatchStatement(String name, MatchPattern pattern) { + this.name = name; + this.pattern = pattern; + this.generatorClass = null; + } + + public MatchStatement(String name, MatchPattern pattern, Class generator) { + this.name = name; + this.pattern = pattern; + this.generatorClass = generator; + } + + /** + * Attempt to match the current statement against a Node. + * + * @param builder the current builder instance. + * @param node the node to be matched + * @param nodes the nodes in the current block + * @return true if the statement matched something and set a {@link ComplexMatchResult} to be + * evaluated by the NodeLIRBuilder. + */ + public boolean generate(NodeLIRBuilder builder, ValueNode node, List nodes) { + MatchContext context = new MatchContext(builder, this, node, nodes); + Result result = pattern.match(node, context); + if (result == Result.OK) { + result = context.validate(); + } + if (result == Result.OK) { + MatchGenerator generator = null; + try { + generator = generatorClass.newInstance(); + // Transfer values into gen + context.transferState(generator); + ComplexMatchResult value = generator.match(builder); + if (value != null) { + context.setResult(value); + return true; + } + } catch (InstantiationException | IllegalAccessException e) { + throw new GraalInternalError(e); + } + } else { + // This is fairly verbose for normal usage. + // if (result.code != MatchResultCode.WRONG_CLASS) { + // // Don't bother logging if it's just the wrong shape. + // Debug.log("while matching %s|%s %s %s %s", context.getRoot().toString(Verbosity.Id), + // context.getRoot().getClass().getSimpleName(), getName(), result, node.graph()); + // } + } + return false; + } + + public String formatMatch(ValueNode root) { + return pattern.formatMatch(root); + } + + public MatchPattern getPattern() { + return pattern; + } + + public String getName() { + return name; + } +} diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/match/MatchStatementSet.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/match/MatchStatementSet.java Mon Apr 28 11:18:15 2014 +0200 @@ -0,0 +1,40 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.graal.compiler.match; + +import java.util.*; + +import com.oracle.graal.compiler.gen.*; + +public interface MatchStatementSet { + /** + * @return the {@link NodeLIRBuilder} subclass which defined this set of {@link MatchStatement} + * instances. + */ + public Class forClass(); + + /** + * @return the {@link MatchStatement}s available with this {@link NodeLIRBuilder} subclass. + */ + public List statements(); +} diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/match/MatchableNode.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/match/MatchableNode.java Mon Apr 28 11:18:15 2014 +0200 @@ -0,0 +1,66 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.graal.compiler.match; + +import java.lang.annotation.*; + +import com.oracle.graal.nodes.*; + +/** + * Describes the properties of a node for use when building a {@link MatchPattern}s. + */ +@Retention(RetentionPolicy.RUNTIME) +@Target(ElementType.TYPE) +@Repeatable(value = MatchableNodes.class) +public @interface MatchableNode { + + /** + * The {@link ValueNode} subclass this annotation describes. These annotations might work better + * if they were directly on the node being described but that may complicate the annotation + * processing. + */ + Class value(); + + /** + * The name used in match patterns. Defaults to class.getSimpleName() with the word Node removed + * from the end. + */ + String shortName() default ""; + + /** + * The number of matchable inputs, which may be less than the real number of inputs. + */ + int inputs() default 0; + + /** + * A helper class to visit the inputs in a specified order. Should be a subclass of + * {@link MatchNodeAdapter}. + */ + Class adapter() default MatchableNode.class; + + /** + * Can a pattern be matched with the operands swapped. This will cause swapped versions of + * patterns to be automatically generated. + */ + boolean commutative() default false; +} diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/match/MatchableNodeImport.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/match/MatchableNodeImport.java Mon Apr 28 11:18:15 2014 +0200 @@ -0,0 +1,36 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.graal.compiler.match; + +import java.lang.annotation.*; + +/** + * A list of classes which contain one or more {@link MatchableNode} annotations describing nodes + * that may be used in match expressions. Those {@link MatchableNode} declarations are parsed before + * processing any {@link MatchRule}s. + */ +@Retention(RetentionPolicy.RUNTIME) +@Target(ElementType.TYPE) +public @interface MatchableNodeImport { + String[] value() default {}; +} diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/match/MatchableNodes.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/match/MatchableNodes.java Mon Apr 28 11:18:15 2014 +0200 @@ -0,0 +1,34 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.graal.compiler.match; + +import java.lang.annotation.*; + +/** + * The repeatable representation of {@link MatchableNode}. Should never be used directly. + */ +@Retention(RetentionPolicy.RUNTIME) +@Target(ElementType.TYPE) +public @interface MatchableNodes { + MatchableNode[] value() default {}; +} diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/phases/HighTier.java --- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/phases/HighTier.java Fri Apr 25 16:21:07 2014 +0200 +++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/phases/HighTier.java Mon Apr 28 11:18:15 2014 +0200 @@ -22,14 +22,15 @@ */ package com.oracle.graal.compiler.phases; +import static com.oracle.graal.compiler.common.GraalOptions.*; import static com.oracle.graal.compiler.phases.HighTier.Options.*; -import static com.oracle.graal.phases.GraalOptions.*; import com.oracle.graal.loop.phases.*; import com.oracle.graal.nodes.spi.*; import com.oracle.graal.options.*; import com.oracle.graal.phases.*; import com.oracle.graal.phases.common.*; +import com.oracle.graal.phases.common.cfs.IterativeFlowSensitiveReductionPhase; import com.oracle.graal.phases.tiers.*; import com.oracle.graal.virtual.phases.ea.*; @@ -57,9 +58,14 @@ appendPhase(new InliningPhase(canonicalizer)); appendPhase(new DeadCodeEliminationPhase()); - if (ConditionalElimination.getValue() && OptCanonicalizer.getValue()) { + boolean reduceOrEliminate = FlowSensitiveReduction.getValue() || ConditionalElimination.getValue(); + if (reduceOrEliminate && OptCanonicalizer.getValue()) { appendPhase(canonicalizer); - appendPhase(new IterativeConditionalEliminationPhase(canonicalizer)); + if (FlowSensitiveReduction.getValue()) { + appendPhase(new IterativeFlowSensitiveReductionPhase(canonicalizer)); + } else { + appendPhase(new IterativeConditionalEliminationPhase(canonicalizer)); + } } } } diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/phases/LowTier.java --- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/phases/LowTier.java Fri Apr 25 16:21:07 2014 +0200 +++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/phases/LowTier.java Mon Apr 28 11:18:15 2014 +0200 @@ -22,7 +22,7 @@ */ package com.oracle.graal.compiler.phases; -import static com.oracle.graal.phases.GraalOptions.*; +import static com.oracle.graal.compiler.common.GraalOptions.*; import com.oracle.graal.nodes.spi.*; import com.oracle.graal.options.*; diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/phases/MidTier.java --- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/phases/MidTier.java Fri Apr 25 16:21:07 2014 +0200 +++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/phases/MidTier.java Mon Apr 28 11:18:15 2014 +0200 @@ -22,7 +22,7 @@ */ package com.oracle.graal.compiler.phases; -import static com.oracle.graal.phases.GraalOptions.*; +import static com.oracle.graal.compiler.common.GraalOptions.*; import com.oracle.graal.loop.phases.*; import com.oracle.graal.nodes.spi.*; @@ -51,9 +51,7 @@ } if (OptFloatingReads.getValue()) { - IncrementalCanonicalizerPhase incCanonicalizer = new IncrementalCanonicalizerPhase<>(canonicalizer); - incCanonicalizer.appendPhase(new FloatingReadPhase()); - appendPhase(incCanonicalizer); + appendPhase(new IncrementalCanonicalizerPhase<>(canonicalizer, new FloatingReadPhase())); if (OptReadElimination.getValue()) { appendPhase(new ReadEliminationPhase()); } @@ -84,7 +82,7 @@ appendPhase(new LoopSafepointInsertionPhase()); - appendPhase(new GuardLoweringPhase()); + appendPhase(new IncrementalCanonicalizerPhase<>(canonicalizer, new GuardLoweringPhase())); appendPhase(new LoweringPhase(canonicalizer, LoweringTool.StandardLoweringStage.MID_TIER)); diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/target/Backend.java --- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/target/Backend.java Fri Apr 25 16:21:07 2014 +0200 +++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/target/Backend.java Mon Apr 28 11:18:15 2014 +0200 @@ -26,11 +26,13 @@ import com.oracle.graal.api.code.stack.*; import com.oracle.graal.api.meta.*; import com.oracle.graal.asm.*; +import com.oracle.graal.compiler.common.*; import com.oracle.graal.compiler.gen.*; -import com.oracle.graal.graph.*; import com.oracle.graal.lir.*; import com.oracle.graal.lir.asm.*; +import com.oracle.graal.lir.gen.*; import com.oracle.graal.nodes.*; +import com.oracle.graal.nodes.spi.*; import com.oracle.graal.phases.tiers.*; import com.oracle.graal.phases.util.*; @@ -71,17 +73,17 @@ */ public abstract FrameMap newFrameMap(RegisterConfig registerConfig); - public abstract LIRGenerator newLIRGenerator(CallingConvention cc, LIRGenerationResult lirGenRes); + public abstract LIRGeneratorTool newLIRGenerator(CallingConvention cc, LIRGenerationResult lirGenRes); public abstract LIRGenerationResult newLIRGenerationResult(LIR lir, FrameMap frameMap, Object stub); - public abstract NodeLIRBuilder newNodeLIRGenerator(StructuredGraph graph, LIRGenerator lirGen); + public abstract NodeLIRBuilderTool newNodeLIRBuilder(StructuredGraph graph, LIRGeneratorTool lirGen); /** * @param gen the LIRGenerator the BytecodeLIRBuilder should use * @param parser the bytecode parser the BytecodeLIRBuilder should use */ - public BytecodeLIRBuilder newBytecodeLIRBuilder(LIRGenerator gen, BytecodeParserTool parser) { + public BytecodeLIRBuilder newBytecodeLIRBuilder(LIRGeneratorTool gen, BytecodeParserTool parser) { throw GraalInternalError.unimplemented("Baseline compilation is not available for this Backend!"); } @@ -102,9 +104,8 @@ /** * Emits the code for a given graph. * - * @param installedCodeOwner the method the compiled code will be - * {@linkplain InstalledCode#getMethod() associated} with once installed. This - * argument can be null. + * @param installedCodeOwner the method the compiled code will be associated with once + * installed. This argument can be null. */ public abstract void emitCode(CompilationResultBuilder crb, LIR lir, ResolvedJavaMethod installedCodeOwner); diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/target/LIRGenLowerable.java --- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/target/LIRGenLowerable.java Fri Apr 25 16:21:07 2014 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,36 +0,0 @@ -/* - * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -package com.oracle.graal.compiler.target; - -import com.oracle.graal.compiler.gen.*; -import com.oracle.graal.lir.*; -import com.oracle.graal.nodes.spi.*; - -/** - * An alternative to {@link LIRLowerable} for lowering that is tightly coupled to - * {@link LIRGenerator} and {@link LIRInstruction}. - */ -public interface LIRGenLowerable { - - void generate(NodeLIRBuilder generator); -} diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/target/LIRGenResLowerable.java --- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/target/LIRGenResLowerable.java Fri Apr 25 16:21:07 2014 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,36 +0,0 @@ -/* - * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -package com.oracle.graal.compiler.target; - -import com.oracle.graal.compiler.gen.*; -import com.oracle.graal.lir.*; -import com.oracle.graal.nodes.spi.*; - -/** - * An alternative to {@link LIRLowerable} for lowering that is tightly coupled to - * {@link LIRGenerationResult} and {@link LIRInstruction}. - */ -public interface LIRGenResLowerable { - - void generate(NodeLIRBuilderTool generator, LIRGenerationResult genRes); -} diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.debug/src/com/oracle/graal/debug/Debug.java --- a/graal/com.oracle.graal.debug/src/com/oracle/graal/debug/Debug.java Fri Apr 25 16:21:07 2014 +0200 +++ b/graal/com.oracle.graal.debug/src/com/oracle/graal/debug/Debug.java Mon Apr 28 11:18:15 2014 +0200 @@ -23,6 +23,7 @@ package com.oracle.graal.debug; import static com.oracle.graal.debug.Debug.Initialization.*; +import static com.oracle.graal.debug.DelegatingDebugConfig.Feature.*; import static java.util.FormattableFlags.*; import java.io.*; @@ -187,6 +188,19 @@ /** * @see #scope(Object) + * @param contextObjects an array of object to be appended to the {@linkplain #context() + * current} debug context + */ + public static Scope scope(Object name, Object[] contextObjects) { + if (ENABLED) { + return DebugScope.getInstance().scope(convertFormatArg(name).toString(), null, contextObjects); + } else { + return null; + } + } + + /** + * @see #scope(Object) * @param context an object to be appended to the {@linkplain #context() current} debug context */ public static Scope scope(Object name, Object context) { @@ -259,17 +273,25 @@ } public static Scope forceLog() { - return Debug.sandbox("forceLog", new DelegatingDebugConfig(DebugScope.getConfig()) { - @Override - public boolean isLogEnabled() { - return true; - } + return Debug.sandbox("forceLog", new DelegatingDebugConfig().enable(LOG).enable(LOG_METHOD)); + } - @Override - public boolean isLogEnabledForMethod() { - return true; - } - }); + /** + * Opens a scope in which exception {@linkplain DebugConfig#interceptException(Throwable) + * interception} is disabled. It is recommended to use the try-with-resource statement for + * managing entering and leaving such scopes: + * + *
+     * try (DebugConfigScope s = Debug.disableIntercept()) {
+     *     ...
+     * }
+     * 
+ * + * This is particularly useful to suppress extraneous output in JUnit tests that are expected to + * throw an exception. + */ + public static DebugConfigScope disableIntercept() { + return Debug.setConfig(new DelegatingDebugConfig().disable(INTERCEPT)); } /** diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.debug/src/com/oracle/graal/debug/DelegatingDebugConfig.java --- a/graal/com.oracle.graal.debug/src/com/oracle/graal/debug/DelegatingDebugConfig.java Fri Apr 25 16:21:07 2014 +0200 +++ b/graal/com.oracle.graal.debug/src/com/oracle/graal/debug/DelegatingDebugConfig.java Mon Apr 28 11:18:15 2014 +0200 @@ -25,45 +25,139 @@ import java.io.*; import java.util.*; +import com.oracle.graal.debug.internal.*; + public class DelegatingDebugConfig implements DebugConfig { protected final DebugConfig delegate; + /** + * The features of a {@link DelegatingDebugConfig} that can be force + * {@linkplain DelegatingDebugConfig#enable(Feature) enabled}/ + * {@linkplain DelegatingDebugConfig#disable(Feature) disabled} or + * {@linkplain DelegatingDebugConfig#delegate(Feature) delegated}. + */ + public enum Feature { + /** + * @see Debug#isLogEnabled() + */ + LOG, + /** + * @see Debug#isLogEnabledForMethod() + */ + LOG_METHOD, + /** + * @see Debug#isDumpEnabled() + */ + DUMP, + /** + * @see Debug#isDumpEnabledForMethod() + */ + DUMP_METHOD, + /** + * @see Debug#isMeterEnabled() + */ + METER, + /** + * @see Debug#isTimeEnabled() + */ + TIME, + /** + * @see DebugConfig#interceptException(Throwable) + */ + INTERCEPT + } + + private final Map featureState = new EnumMap<>(Feature.class); + + /** + * Creates a config that delegates to the {@link DebugScope#getConfig() current config}. + */ + public DelegatingDebugConfig() { + this(DebugScope.getConfig()); + } + + /** + * Creates a config that delegates to a given config. + */ public DelegatingDebugConfig(DebugConfig delegate) { this.delegate = delegate; } + public DelegatingDebugConfig enable(Feature feature) { + featureState.put(feature, Boolean.TRUE); + return this; + } + + public DelegatingDebugConfig disable(Feature feature) { + featureState.put(feature, Boolean.FALSE); + return this; + } + + public DelegatingDebugConfig delegate(Feature feature) { + featureState.put(feature, null); + return this; + } + @Override public boolean isLogEnabled() { - return delegate.isLogEnabled(); + Boolean fs = featureState.get(Feature.LOG); + if (fs == null) { + return delegate.isLogEnabled(); + } + return fs.booleanValue(); } public boolean isLogEnabledForMethod() { - return delegate.isLogEnabledForMethod(); + Boolean fs = featureState.get(Feature.LOG_METHOD); + if (fs == null) { + return delegate.isLogEnabledForMethod(); + } + return fs.booleanValue(); } @Override public boolean isMeterEnabled() { - return delegate.isMeterEnabled(); + Boolean fs = featureState.get(Feature.METER); + if (fs == null) { + return delegate.isMeterEnabled(); + } + return fs.booleanValue(); } @Override public boolean isDumpEnabled() { - return delegate.isDumpEnabled(); + Boolean fs = featureState.get(Feature.DUMP); + if (fs == null) { + return delegate.isDumpEnabled(); + } + return fs.booleanValue(); } public boolean isDumpEnabledForMethod() { - return delegate.isDumpEnabledForMethod(); + Boolean fs = featureState.get(Feature.DUMP_METHOD); + if (fs == null) { + return delegate.isDumpEnabledForMethod(); + } + return fs.booleanValue(); } @Override public boolean isTimeEnabled() { - return delegate.isTimeEnabled(); + Boolean fs = featureState.get(Feature.TIME); + if (fs == null) { + return delegate.isTimeEnabled(); + } + return fs.booleanValue(); } @Override public RuntimeException interceptException(Throwable e) { - return delegate.interceptException(e); + Boolean fs = featureState.get(Feature.INTERCEPT); + if (fs == null || fs) { + return delegate.interceptException(e); + } + return null; } @Override diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.graph.test/src/com/oracle/graal/graph/test/NodeUsagesTests.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.graph.test/src/com/oracle/graal/graph/test/NodeUsagesTests.java Mon Apr 28 11:18:15 2014 +0200 @@ -0,0 +1,425 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.graal.graph.test; + +import static com.oracle.graal.graph.test.matchers.NodeIterableContains.*; +import static com.oracle.graal.graph.test.matchers.NodeIterableIsEmpty.*; +import static org.junit.Assert.*; + +import org.junit.*; + +import com.oracle.graal.graph.*; + +public class NodeUsagesTests { + + private static class Def extends Node { + + } + + private static class Use extends Node { + private @Input Def in0; + private @Input Def in1; + private @Input Def in2; + + public Use(Def in0, Def in1, Def in2) { + this.in0 = in0; + this.in1 = in1; + this.in2 = in2; + } + } + + @Test + public void testReplaceAtUsages() { + Graph graph = new Graph(); + Def def0 = graph.add(new Def()); + Def def1 = graph.add(new Def()); + Use use0 = graph.add(new Use(def0, null, null)); + Use use1 = graph.add(new Use(null, def0, null)); + Use use2 = graph.add(new Use(null, null, def0)); + + assertEquals(3, def0.usages().count()); + assertThat(def0.usages(), contains(use0)); + assertThat(def0.usages(), contains(use1)); + assertThat(def0.usages(), contains(use2)); + + assertThat(def0.usages(), isNotEmpty()); + assertThat(def1.usages(), isEmpty()); + + def0.replaceAtUsages(def1); + + assertThat(def0.usages(), isEmpty()); + + assertEquals(3, def1.usages().count()); + assertThat(def1.usages(), contains(use0)); + assertThat(def1.usages(), contains(use1)); + assertThat(def1.usages(), contains(use2)); + + assertThat(def1.usages(), isNotEmpty()); + } + + @Test + public void testReplaceAtUsagesWithPredicateAll() { + Graph graph = new Graph(); + Def def0 = graph.add(new Def()); + Def def1 = graph.add(new Def()); + Use use0 = graph.add(new Use(def0, null, null)); + Use use1 = graph.add(new Use(null, def0, null)); + Use use2 = graph.add(new Use(null, null, def0)); + + assertEquals(3, def0.usages().count()); + assertThat(def0.usages(), contains(use0)); + assertThat(def0.usages(), contains(use1)); + assertThat(def0.usages(), contains(use2)); + + assertThat(def0.usages(), isNotEmpty()); + assertThat(def1.usages(), isEmpty()); + + def0.replaceAtMatchingUsages(def1, u -> true); + + assertThat(def0.usages(), isEmpty()); + + assertEquals(3, def1.usages().count()); + assertThat(def1.usages(), contains(use0)); + assertThat(def1.usages(), contains(use1)); + assertThat(def1.usages(), contains(use2)); + + assertThat(def1.usages(), isNotEmpty()); + } + + @Test + public void testReplaceAtUsagesWithPredicateNone() { + Graph graph = new Graph(); + Def def0 = graph.add(new Def()); + Def def1 = graph.add(new Def()); + Use use0 = graph.add(new Use(def0, null, null)); + Use use1 = graph.add(new Use(null, def0, null)); + Use use2 = graph.add(new Use(null, null, def0)); + + assertEquals(3, def0.usages().count()); + assertThat(def0.usages(), contains(use0)); + assertThat(def0.usages(), contains(use1)); + assertThat(def0.usages(), contains(use2)); + + assertThat(def0.usages(), isNotEmpty()); + assertThat(def1.usages(), isEmpty()); + + def0.replaceAtMatchingUsages(def1, u -> false); + + assertThat(def1.usages(), isEmpty()); + + assertEquals(3, def0.usages().count()); + assertThat(def0.usages(), contains(use0)); + assertThat(def0.usages(), contains(use1)); + assertThat(def0.usages(), contains(use2)); + + assertThat(def0.usages(), isNotEmpty()); + } + + @Test + public void testReplaceAtUsagesWithPredicate1() { + Graph graph = new Graph(); + Def def0 = graph.add(new Def()); + Def def1 = graph.add(new Def()); + Use use0 = graph.add(new Use(def0, null, null)); + Use use1 = graph.add(new Use(null, def0, null)); + Use use2 = graph.add(new Use(null, null, def0)); + + assertEquals(3, def0.usages().count()); + assertThat(def0.usages(), contains(use0)); + assertThat(def0.usages(), contains(use1)); + assertThat(def0.usages(), contains(use2)); + + assertThat(def0.usages(), isNotEmpty()); + assertThat(def1.usages(), isEmpty()); + + def0.replaceAtMatchingUsages(def1, u -> u == use1); + + assertEquals(1, def1.usages().count()); + assertThat(def1.usages(), contains(use1)); + + assertThat(def1.usages(), isNotEmpty()); + + assertEquals(2, def0.usages().count()); + assertThat(def0.usages(), contains(use0)); + assertThat(def0.usages(), contains(use2)); + + assertThat(def0.usages(), isNotEmpty()); + } + + @Test + public void testReplaceAtUsagesWithPredicate2() { + Graph graph = new Graph(); + Def def0 = graph.add(new Def()); + Def def1 = graph.add(new Def()); + Use use0 = graph.add(new Use(def0, null, null)); + Use use1 = graph.add(new Use(null, def0, null)); + Use use2 = graph.add(new Use(null, null, def0)); + + assertEquals(3, def0.usages().count()); + assertThat(def0.usages(), contains(use0)); + assertThat(def0.usages(), contains(use1)); + assertThat(def0.usages(), contains(use2)); + + assertThat(def0.usages(), isNotEmpty()); + assertThat(def1.usages(), isEmpty()); + + def0.replaceAtMatchingUsages(def1, u -> u == use2); + + assertEquals(1, def1.usages().count()); + assertThat(def1.usages(), contains(use2)); + + assertThat(def1.usages(), isNotEmpty()); + + assertEquals(2, def0.usages().count()); + assertThat(def0.usages(), contains(use0)); + assertThat(def0.usages(), contains(use1)); + + assertThat(def0.usages(), isNotEmpty()); + } + + @Test + public void testReplaceAtUsagesWithPredicate0() { + Graph graph = new Graph(); + Def def0 = graph.add(new Def()); + Def def1 = graph.add(new Def()); + Use use0 = graph.add(new Use(def0, null, null)); + Use use1 = graph.add(new Use(null, def0, null)); + Use use2 = graph.add(new Use(null, null, def0)); + + assertEquals(3, def0.usages().count()); + assertThat(def0.usages(), contains(use0)); + assertThat(def0.usages(), contains(use1)); + assertThat(def0.usages(), contains(use2)); + + assertThat(def0.usages(), isNotEmpty()); + assertThat(def1.usages(), isEmpty()); + + def0.replaceAtMatchingUsages(def1, u -> u == use0); + + assertEquals(1, def1.usages().count()); + assertThat(def1.usages(), contains(use0)); + + assertThat(def1.usages(), isNotEmpty()); + + assertEquals(2, def0.usages().count()); + assertThat(def0.usages(), contains(use1)); + assertThat(def0.usages(), contains(use2)); + + assertThat(def0.usages(), isNotEmpty()); + } + + @Test + public void testReplaceAtUsagesWithPredicate02() { + Graph graph = new Graph(); + Def def0 = graph.add(new Def()); + Def def1 = graph.add(new Def()); + Use use0 = graph.add(new Use(def0, null, null)); + Use use1 = graph.add(new Use(null, def0, null)); + Use use2 = graph.add(new Use(null, null, def0)); + + assertEquals(3, def0.usages().count()); + assertThat(def0.usages(), contains(use0)); + assertThat(def0.usages(), contains(use1)); + assertThat(def0.usages(), contains(use2)); + + assertThat(def0.usages(), isNotEmpty()); + assertThat(def1.usages(), isEmpty()); + + def0.replaceAtMatchingUsages(def1, u -> u != use1); + + assertEquals(1, def0.usages().count()); + assertThat(def0.usages(), contains(use1)); + + assertThat(def0.usages(), isNotEmpty()); + + assertEquals(2, def1.usages().count()); + assertThat(def1.usages(), contains(use0)); + assertThat(def1.usages(), contains(use2)); + + assertThat(def1.usages(), isNotEmpty()); + } + + @Test + public void testReplaceAtUsagesWithPredicate023() { + Graph graph = new Graph(); + Def def0 = graph.add(new Def()); + Def def1 = graph.add(new Def()); + Use use0 = graph.add(new Use(def0, null, null)); + Use use1 = graph.add(new Use(null, def0, null)); + Use use2 = graph.add(new Use(null, null, def0)); + Use use3 = graph.add(new Use(null, null, def0)); + + assertEquals(4, def0.usages().count()); + assertThat(def0.usages(), contains(use0)); + assertThat(def0.usages(), contains(use1)); + assertThat(def0.usages(), contains(use2)); + assertThat(def0.usages(), contains(use3)); + + assertThat(def0.usages(), isNotEmpty()); + assertThat(def1.usages(), isEmpty()); + + def0.replaceAtMatchingUsages(def1, u -> u != use1); + + assertEquals(1, def0.usages().count()); + assertThat(def0.usages(), contains(use1)); + + assertThat(def0.usages(), isNotEmpty()); + + assertEquals(3, def1.usages().count()); + assertThat(def1.usages(), contains(use0)); + assertThat(def1.usages(), contains(use2)); + assertThat(def1.usages(), contains(use3)); + + assertThat(def1.usages(), isNotEmpty()); + } + + @Test + public void testReplaceAtUsagesWithPredicate013() { + Graph graph = new Graph(); + Def def0 = graph.add(new Def()); + Def def1 = graph.add(new Def()); + Use use0 = graph.add(new Use(def0, null, null)); + Use use1 = graph.add(new Use(null, def0, null)); + Use use2 = graph.add(new Use(null, null, def0)); + Use use3 = graph.add(new Use(null, null, def0)); + + assertEquals(4, def0.usages().count()); + assertThat(def0.usages(), contains(use0)); + assertThat(def0.usages(), contains(use1)); + assertThat(def0.usages(), contains(use2)); + assertThat(def0.usages(), contains(use3)); + + assertThat(def0.usages(), isNotEmpty()); + assertThat(def1.usages(), isEmpty()); + + def0.replaceAtMatchingUsages(def1, u -> u != use2); + + assertEquals(1, def0.usages().count()); + assertThat(def0.usages(), contains(use2)); + + assertThat(def0.usages(), isNotEmpty()); + + assertEquals(3, def1.usages().count()); + assertThat(def1.usages(), contains(use0)); + assertThat(def1.usages(), contains(use1)); + assertThat(def1.usages(), contains(use3)); + + assertThat(def1.usages(), isNotEmpty()); + } + + @Test + public void testReplaceAtUsagesWithPredicate2_3() { + Graph graph = new Graph(); + Def def0 = graph.add(new Def()); + Def def1 = graph.add(new Def()); + Use use0 = graph.add(new Use(def0, null, null)); + Use use1 = graph.add(new Use(null, def0, null)); + Use use2 = graph.add(new Use(null, null, def0)); + Use use3 = graph.add(new Use(null, null, def0)); + + assertEquals(4, def0.usages().count()); + assertThat(def0.usages(), contains(use0)); + assertThat(def0.usages(), contains(use1)); + assertThat(def0.usages(), contains(use2)); + assertThat(def0.usages(), contains(use3)); + + assertThat(def0.usages(), isNotEmpty()); + assertThat(def1.usages(), isEmpty()); + + def0.replaceAtMatchingUsages(def1, u -> u == use2); + + assertEquals(1, def1.usages().count()); + assertThat(def1.usages(), contains(use2)); + + assertThat(def1.usages(), isNotEmpty()); + + assertEquals(3, def0.usages().count()); + assertThat(def0.usages(), contains(use0)); + assertThat(def0.usages(), contains(use1)); + assertThat(def0.usages(), contains(use3)); + + assertThat(def0.usages(), isNotEmpty()); + } + + @Test + public void testReplaceAtUsagesWithPredicate01() { + Graph graph = new Graph(); + Def def0 = graph.add(new Def()); + Def def1 = graph.add(new Def()); + Use use0 = graph.add(new Use(def0, null, null)); + Use use1 = graph.add(new Use(null, def0, null)); + Use use2 = graph.add(new Use(null, null, def0)); + + assertEquals(3, def0.usages().count()); + assertThat(def0.usages(), contains(use0)); + assertThat(def0.usages(), contains(use1)); + assertThat(def0.usages(), contains(use2)); + + assertThat(def0.usages(), isNotEmpty()); + assertThat(def1.usages(), isEmpty()); + + def0.replaceAtMatchingUsages(def1, u -> u != use2); + + assertEquals(1, def0.usages().count()); + assertThat(def0.usages(), contains(use2)); + + assertThat(def0.usages(), isNotEmpty()); + + assertEquals(2, def1.usages().count()); + assertThat(def1.usages(), contains(use0)); + assertThat(def1.usages(), contains(use1)); + + assertThat(def1.usages(), isNotEmpty()); + } + + @Test + public void testReplaceAtUsagesWithPredicate12() { + Graph graph = new Graph(); + Def def0 = graph.add(new Def()); + Def def1 = graph.add(new Def()); + Use use0 = graph.add(new Use(def0, null, null)); + Use use1 = graph.add(new Use(null, def0, null)); + Use use2 = graph.add(new Use(null, null, def0)); + + assertEquals(3, def0.usages().count()); + assertThat(def0.usages(), contains(use0)); + assertThat(def0.usages(), contains(use1)); + assertThat(def0.usages(), contains(use2)); + + assertThat(def0.usages(), isNotEmpty()); + assertThat(def1.usages(), isEmpty()); + + def0.replaceAtMatchingUsages(def1, u -> u != use0); + + assertEquals(1, def0.usages().count()); + assertThat(def0.usages(), contains(use0)); + + assertThat(def0.usages(), isNotEmpty()); + + assertEquals(2, def1.usages().count()); + assertThat(def1.usages(), contains(use1)); + assertThat(def1.usages(), contains(use2)); + + assertThat(def1.usages(), isNotEmpty()); + } +} diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.graph.test/src/com/oracle/graal/graph/test/matchers/NodeIterableContains.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.graph.test/src/com/oracle/graal/graph/test/matchers/NodeIterableContains.java Mon Apr 28 11:18:15 2014 +0200 @@ -0,0 +1,53 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.graal.graph.test.matchers; + +import org.hamcrest.*; + +import com.oracle.graal.graph.*; +import com.oracle.graal.graph.iterators.*; + +public class NodeIterableContains extends TypeSafeDiagnosingMatcher> { + private T node; + + public NodeIterableContains(T node) { + this.node = node; + } + + public void describeTo(Description description) { + description.appendText("is a NodeIterable containing").appendValue(node); + } + + public static NodeIterableContains contains(T node) { + return new NodeIterableContains<>(node); + } + + public static NodeIterableContains d(T node) { + return new NodeIterableContains<>(node); + } + + @Override + protected boolean matchesSafely(NodeIterable iterable, Description description) { + return iterable.contains(node); + } +} diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.graph.test/src/com/oracle/graal/graph/test/matchers/NodeIterableIsEmpty.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.graph.test/src/com/oracle/graal/graph/test/matchers/NodeIterableIsEmpty.java Mon Apr 28 11:18:15 2014 +0200 @@ -0,0 +1,49 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.graal.graph.test.matchers; + +import org.hamcrest.*; +import org.hamcrest.core.*; + +import com.oracle.graal.graph.iterators.*; + +public class NodeIterableIsEmpty extends BaseMatcher> { + + private static final NodeIterableIsEmpty INSTANCE = new NodeIterableIsEmpty(); + + public boolean matches(Object iterable) { + return iterable instanceof NodeIterable && ((NodeIterable) iterable).isEmpty(); + } + + public void describeTo(Description description) { + description.appendText("is an empty NodeIterable"); + } + + public static Matcher> isEmpty() { + return INSTANCE; + } + + public static Matcher> isNotEmpty() { + return IsNot.not(INSTANCE); + } +} diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.graph/src/com/oracle/graal/graph/FieldIntrospection.java --- a/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/FieldIntrospection.java Fri Apr 25 16:21:07 2014 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,153 +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.graph; - -import java.lang.reflect.*; -import java.util.*; -import java.util.concurrent.*; - -public abstract class FieldIntrospection extends UnsafeAccess { - - /** - * Interface used by {@link #rescanAllFieldOffsets(CalcOffset)} to determine the offset (in - * bytes) of a field. - */ - public interface CalcOffset { - - long getOffset(Field field); - } - - public static class DefaultCalcOffset implements CalcOffset { - - @Override - public long getOffset(Field field) { - return unsafe.objectFieldOffset(field); - } - } - - protected static final ConcurrentHashMap, FieldIntrospection> allClasses = new ConcurrentHashMap<>(); - - protected final Class clazz; - protected long[] dataOffsets; - protected Map fieldNames; - protected Map> fieldTypes; - - public FieldIntrospection(Class clazz) { - this.clazz = clazz; - } - - public static void rescanAllFieldOffsets(CalcOffset calc) { - for (FieldIntrospection nodeClass : allClasses.values()) { - nodeClass.rescanFieldOffsets(calc); - } - } - - protected abstract void rescanFieldOffsets(CalcOffset calc); - - public abstract static class BaseFieldScanner { - - private final CalcOffset calc; - - /** The offsets of fields that are not specially handled by subclasses. */ - public final ArrayList dataOffsets = new ArrayList<>(); - - public final Map fieldNames = new HashMap<>(); - public final Map> fieldTypes = new HashMap<>(); - - protected BaseFieldScanner(CalcOffset calc) { - this.calc = calc; - } - - protected void scan(Class clazz) { - Class currentClazz = clazz; - do { - for (Field field : currentClazz.getDeclaredFields()) { - if (Modifier.isStatic(field.getModifiers())) { - continue; - } - Class type = field.getType(); - long offset = calc.getOffset(field); - - // scanField() may overwrite the name with a customized name. - fieldNames.put(offset, field.getName()); - fieldTypes.put(offset, type); - - scanField(field, type, offset); - } - currentClazz = currentClazz.getSuperclass(); - } while (currentClazz.getSuperclass() != Object.class); - } - - protected abstract void scanField(Field field, Class type, long offset); - } - - protected static void copyInto(long[] dest, long[] src) { - assert dest.length == src.length; - for (int i = 0; i < dest.length; i++) { - dest[i] = src[i]; - } - } - - protected static void copyInto(T[] dest, T[] src) { - assert dest.length == src.length; - for (int i = 0; i < dest.length; i++) { - dest[i] = src[i]; - } - } - - protected static void copyInto(T[] dest, List src) { - assert dest.length == src.size(); - for (int i = 0; i < dest.length; i++) { - dest[i] = src.get(i); - } - } - - protected static T[] arrayUsingSortedOffsets(Map map, long[] sortedOffsets, T[] result) { - for (int i = 0; i < sortedOffsets.length; i++) { - result[i] = map.get(sortedOffsets[i]); - } - return result; - } - - protected static long[] sortedLongCopy(ArrayList list1) { - Collections.sort(list1); - long[] result = new long[list1.size()]; - for (int i = 0; i < list1.size(); i++) { - result[i] = list1.get(i); - } - return result; - } - - protected static long[] sortedLongCopy(ArrayList list1, ArrayList list2) { - Collections.sort(list1); - Collections.sort(list2); - long[] result = new long[list1.size() + list2.size()]; - for (int i = 0; i < list1.size(); i++) { - result[i] = list1.get(i); - } - for (int i = 0; i < list2.size(); i++) { - result[list1.size() + i] = list2.get(i); - } - return result; - } -} diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.graph/src/com/oracle/graal/graph/GraalGraphInternalError.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/GraalGraphInternalError.java Mon Apr 28 11:18:15 2014 +0200 @@ -0,0 +1,148 @@ +/* + * Copyright (c) 2011, 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.graal.graph; + +import com.oracle.graal.compiler.common.*; + +/** + * This error is the graph/node aware extension of GraalInternalError. + */ +public class GraalGraphInternalError extends GraalInternalError { + + private static final long serialVersionUID = -989290015525497919L; + private Node node; + private Graph graph; + + /** + * This constructor creates a {@link GraalGraphInternalError} with a message assembled via + * {@link String#format(String, Object...)}. It always uses the ENGLISH locale in order to + * always generate the same output. + * + * @param msg the message that will be associated with the error, in String.format syntax + * @param args parameters to String.format - parameters that implement {@link Iterable} will be + * expanded into a [x, x, ...] representation. + */ + public GraalGraphInternalError(String msg, Object... args) { + super(msg, args); + } + + /** + * This constructor creates a {@link GraalGraphInternalError} for a given causing Throwable + * instance. + * + * @param cause the original exception that contains additional information on this error + */ + public GraalGraphInternalError(Throwable cause) { + super(cause); + } + + /** + * This constructor creates a {@link GraalGraphInternalError} from a given GraalInternalError + * instance. + * + * @param e the original GraalInternalError + */ + protected GraalGraphInternalError(GraalInternalError e) { + super(e); + if (e instanceof GraalGraphInternalError) { + node = ((GraalGraphInternalError) e).node; + graph = ((GraalGraphInternalError) e).graph; + } + } + + /** + * Adds a graph to the context of this VerificationError. The first graph added via this method + * will be returned by {@link #graph()}. + * + * @param newGraph the graph which is in a incorrect state, if the verification error was not + * caused by a specific node + */ + GraalGraphInternalError addContext(Graph newGraph) { + if (newGraph != this.graph) { + addContext("graph", newGraph); + if (this.graph == null) { + this.graph = newGraph; + } + } + return this; + } + + /** + * Adds a node to the context of this VerificationError. The first node added via this method + * will be returned by {@link #node()}. + * + * @param newNode the node which is in a incorrect state, if the verification error was caused + * by a node + */ + public GraalGraphInternalError addContext(Node newNode) { + if (newNode != this.node) { + addContext("node", newNode); + if (this.node == null) { + this.node = newNode; + } + } + return this; + } + + /** + * Transform a GraalInternalError into a GraalGraphInternalError and add a graph to the context. + * + * @param e the previous error + * @param newGraph the graph which is in a incorrect state, if the verification error was not + * caused by a specific node + */ + public static GraalGraphInternalError transformAndAddContext(GraalInternalError e, Graph newGraph) { + GraalGraphInternalError graphError; + if (e instanceof GraalGraphInternalError) { + graphError = (GraalGraphInternalError) e; + } else { + graphError = new GraalGraphInternalError(e); + } + return graphError.addContext(newGraph); + } + + /** + * Transform a GraalInternalError into a GraalGraphInternalError and add a node to the context. + * + * @param e the previous error + * @param newNode the node which is in a incorrect state, if the verification error was caused + * by a node + */ + public static GraalGraphInternalError transformAndAddContext(GraalInternalError e, Node newNode) { + GraalGraphInternalError graphError; + if (e instanceof GraalGraphInternalError) { + graphError = (GraalGraphInternalError) e; + } else { + graphError = new GraalGraphInternalError(e); + } + return graphError.addContext(newNode); + } + + public Node node() { + return node; + } + + public Graph graph() { + return graph; + } +} diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.graph/src/com/oracle/graal/graph/GraalInternalError.java --- a/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/GraalInternalError.java Fri Apr 25 16:21:07 2014 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,168 +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; - -import java.util.*; - -/** - * This error represents a conditions that should never occur during normal operation. - */ -public class GraalInternalError extends Error { - - private static final long serialVersionUID = 8776065085829593278L; - private Node node; - private Graph graph; - private final ArrayList context = new ArrayList<>(); - - public static RuntimeException unimplemented() { - throw new GraalInternalError("unimplemented"); - } - - public static RuntimeException unimplemented(String msg) { - throw new GraalInternalError("unimplemented: %s", msg); - } - - public static RuntimeException shouldNotReachHere() { - throw new GraalInternalError("should not reach here"); - } - - public static RuntimeException shouldNotReachHere(String msg) { - throw new GraalInternalError("should not reach here: %s", msg); - } - - /** - * Checks a given condition and throws a {@link GraalInternalError} if it is false. Guarantees - * are stronger than assertions in that they are always checked. Error messages for guarantee - * violations should clearly indicate the nature of the problem as well as a suggested solution - * if possible. - * - * @param condition the condition to check - * @param msg the message that will be associated with the error, in - * {@link String#format(String, Object...)} syntax - * @param args arguments to the format string - */ - public static void guarantee(boolean condition, String msg, Object... args) { - if (!condition) { - throw new GraalInternalError("failed guarantee: " + msg, args); - } - } - - /** - * This constructor creates a {@link GraalInternalError} with a message assembled via - * {@link String#format(String, Object...)}. It always uses the ENGLISH locale in order to - * always generate the same output. - * - * @param msg the message that will be associated with the error, in String.format syntax - * @param args parameters to String.format - parameters that implement {@link Iterable} will be - * expanded into a [x, x, ...] representation. - */ - public GraalInternalError(String msg, Object... args) { - super(format(msg, args)); - } - - /** - * This constructor creates a {@link GraalInternalError} for a given causing Throwable instance. - * - * @param cause the original exception that contains additional information on this error - */ - public GraalInternalError(Throwable cause) { - super(cause); - } - - @Override - public String toString() { - StringBuilder str = new StringBuilder(); - str.append(super.toString()); - for (String s : context) { - str.append("\n\tat ").append(s); - } - return str.toString(); - } - - private static String format(String msg, Object... args) { - if (args != null) { - // expand Iterable parameters into a list representation - for (int i = 0; i < args.length; i++) { - if (args[i] instanceof Iterable) { - ArrayList list = new ArrayList<>(); - for (Object o : (Iterable) args[i]) { - list.add(o); - } - args[i] = list.toString(); - } - } - } - return String.format(Locale.ENGLISH, msg, args); - } - - public GraalInternalError addContext(String newContext) { - this.context.add(newContext); - return this; - } - - public GraalInternalError addContext(String name, Object obj) { - return addContext(format("%s: %s", name, obj)); - } - - /** - * Adds a graph to the context of this VerificationError. The first graph added via this method - * will be returned by {@link #graph()}. - * - * @param newGraph the graph which is in a incorrect state, if the verification error was not - * caused by a specific node - */ - public GraalInternalError addContext(Graph newGraph) { - if (newGraph != this.graph) { - addContext("graph", newGraph); - if (this.graph == null) { - this.graph = newGraph; - } - } - return this; - } - - /** - * Adds a node to the context of this VerificationError. The first node added via this method - * will be returned by {@link #node()}. - * - * @param newNode the node which is in a incorrect state, if the verification error was caused - * by a node - */ - public GraalInternalError addContext(Node newNode) { - if (newNode != this.node) { - addContext("node", newNode); - if (this.node == null) { - this.node = newNode; - } - } - return this; - } - - public Node node() { - return node; - } - - public Graph graph() { - return graph; - } -} diff -r 3dde8d8c95b8 -r 40d0022115ee 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 Fri Apr 25 16:21:07 2014 +0200 +++ b/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/Graph.java Mon Apr 28 11:18:15 2014 +0200 @@ -24,6 +24,7 @@ import java.util.*; +import com.oracle.graal.compiler.common.*; import com.oracle.graal.debug.*; import com.oracle.graal.graph.GraphEvent.NodeEvent; import com.oracle.graal.graph.Node.ValueNumberable; @@ -525,7 +526,7 @@ */ public NodeIterable getNewNodes(Mark mark) { final int index = mark.getValue(); - return new AbstractNodeIterable() { + return new NodeIterable() { @Override public Iterator iterator() { @@ -540,7 +541,7 @@ * @return an {@link Iterable} providing all the live nodes. */ public NodeIterable getNodes() { - return new AbstractNodeIterable() { + return new NodeIterable() { @Override public Iterator iterator() { @@ -714,7 +715,7 @@ */ public NodeIterable getNodes(final Class type) { final NodeClass nodeClass = NodeClass.get(type); - return new AbstractNodeIterable() { + return new NodeIterable() { @Override public Iterator iterator() { @@ -839,7 +840,7 @@ throw new GraalInternalError(t); } } catch (GraalInternalError e) { - throw e.addContext(node).addContext(this); + throw GraalGraphInternalError.transformAndAddContext(e, node).addContext(this); } } return true; diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.graph/src/com/oracle/graal/graph/Node.java --- a/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/Node.java Fri Apr 25 16:21:07 2014 +0200 +++ b/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/Node.java Mon Apr 28 11:18:15 2014 +0200 @@ -184,12 +184,10 @@ class NodeUsageIterator implements Iterator { - private final int expectedModCount = usageModCount(); int index = -1; Node current; private void advance() { - assert index == -1 || current != null; current = null; index++; if (index == 0) { @@ -208,12 +206,10 @@ } public boolean hasNext() { - assert expectedModCount == usageModCount(); return current != null; } public Node next() { - assert expectedModCount == usageModCount(); Node result = current; if (result == null) { throw new NoSuchElementException(); @@ -228,10 +224,35 @@ } } - class NodeUsageIterable extends AbstractNodeIterable { + class NodeUsageWithModCountIterator extends NodeUsageIterator { + + private final int expectedModCount = usageModCount(); + + @Override + public boolean hasNext() { + if (expectedModCount != usageModCount()) { + throw new ConcurrentModificationException(); + } + return super.hasNext(); + } + + @Override + public Node next() { + if (expectedModCount != usageModCount()) { + throw new ConcurrentModificationException(); + } + return super.next(); + } + } + + class NodeUsageIterable implements NodeIterable { public NodeUsageIterator iterator() { - return new NodeUsageIterator(); + if (MODIFICATION_COUNTS_ENABLED) { + return new NodeUsageWithModCountIterator(); + } else { + return new NodeUsageIterator(); + } } @Override @@ -246,13 +267,7 @@ @Override public int count() { - if (usage0 == null) { - return 0; - } - if (usage1 == null) { - return 1; - } - return 2 + indexOfLastNonNull(extraUsages) + 1; + return usageCount(); } } @@ -349,6 +364,81 @@ } } + private int usageCount() { + if (usage0 == null) { + return 0; + } + if (usage1 == null) { + return 1; + } + return 2 + indexOfLastNonNull(extraUsages) + 1; + } + + /** + * Remove all usages between {@code fromIndex} and {@code toIndex} (exclusive), also, if + * {@code toIndex} is a valid usage, it is moved to {@code fromIndex}. + * + *

+ * Visually, + * + *

+     * {@code
+     * [1, 2, 3, 4, 5, 6, 7].removeUsagesAndShiftFirst(1, 2) == [1, 4, 6, 7, 5, null, null]}
+     * 
+ * + * + * @param fromIndex the index of the first element to be removed + * @param toIndex the index after the last element to be removed + */ + private void removeUsagesAndShiftFirst(int fromIndex, int toIndex) { + assert fromIndex < toIndex; + int firstNullIndex = usageCount(); + assert toIndex <= firstNullIndex; + int i = fromIndex; + int limit = toIndex; + if (toIndex < firstNullIndex) { + // move usage at toIndex to fromIndex(!) + movUsageTo(toIndex, fromIndex); + limit++; + i++; + } + while (i < limit && firstNullIndex > limit) { + movUsageTo(firstNullIndex - 1, i); + firstNullIndex--; + i++; + } + while (i < limit) { + if (i == 0) { + usage0 = null; + } else if (i == 1) { + usage1 = null; + } else { + extraUsages[i - INLINE_USAGE_COUNT] = null; + } + i++; + } + + } + + private void movUsageTo(int usageIndex, int toIndex) { + assert usageIndex > toIndex; + if (toIndex == 0) { + if (usageIndex == 1) { + usage0 = usage1; + usage1 = null; + } else { + usage0 = extraUsages[usageIndex - INLINE_USAGE_COUNT]; + extraUsages[usageIndex - INLINE_USAGE_COUNT] = null; + } + } else if (toIndex == 1) { + usage1 = extraUsages[usageIndex - INLINE_USAGE_COUNT]; + extraUsages[usageIndex - INLINE_USAGE_COUNT] = null; + } else { + extraUsages[toIndex - INLINE_USAGE_COUNT] = extraUsages[usageIndex - INLINE_USAGE_COUNT]; + extraUsages[usageIndex - INLINE_USAGE_COUNT] = null; + } + } + /** * Removes a given node from this node's {@linkplain #usages() usages}. * @@ -357,6 +447,7 @@ */ private boolean removeUsage(Node node) { assert recordsUsages(); + assert node != null; // It is critical that this method maintains the invariant that // the usage list has no null element preceding a non-null element incUsageModCount(); @@ -388,20 +479,19 @@ } return true; } - int lastNonNull = indexOfLastNonNull(extraUsages); - if (lastNonNull >= 0) { - for (int i = 0; i <= lastNonNull; ++i) { - Node n = extraUsages[i]; - if (n == node) { - if (i < lastNonNull) { - extraUsages[i] = extraUsages[lastNonNull]; - extraUsages[lastNonNull] = null; - } else { - extraUsages[i] = null; - } - return true; - } + int matchIndex = -1; + int i = 0; + Node n; + while (i < extraUsages.length && (n = extraUsages[i]) != null) { + if (n == node) { + matchIndex = i; } + i++; + } + if (matchIndex >= 0) { + extraUsages[matchIndex] = extraUsages[i - 1]; + extraUsages[i - 1] = null; + return true; } return false; } @@ -543,13 +633,47 @@ clearUsages(); } + public void replaceAtMatchingUsages(Node other, NodePredicate usagePredicate) { + assert checkReplaceWith(other); + NodeUsageIterator it = (NodeUsageIterator) usages().iterator(); + int removeStart = -1; + while (it.hasNext()) { + Node usage = it.next(); + if (usagePredicate.apply(usage)) { + if (removeStart < 0) { + removeStart = it.index - 1; + } + boolean result = usage.getNodeClass().replaceFirstInput(usage, this, other); + assert assertTrue(result, "not found in inputs, usage: %s", usage); + if (other != null) { + maybeNotifyChanged(usage); + if (other.recordsUsages()) { + other.addUsage(usage); + } + } + } else { + if (removeStart >= 0) { + int removeEndIndex = it.index - 1; + removeUsagesAndShiftFirst(removeStart, removeEndIndex); + it.index = removeStart; + it.advance(); + removeStart = -1; + } + } + } + if (removeStart >= 0) { + int removeEndIndex = it.index; + removeUsagesAndShiftFirst(removeStart, removeEndIndex); + } + } + public void replaceAtUsages(InputType type, Node other) { assert checkReplaceWith(other); for (Node usage : usages().snapshot()) { NodeClassIterator iter = usage.inputs().iterator(); while (iter.hasNext()) { Position pos = iter.nextPosition(); - if (pos.getInputType(usage) == type) { + if (pos.getInputType(usage) == type && pos.get(usage) == this) { pos.set(usage, other); } } @@ -707,7 +831,7 @@ try { newNode = (Node) this.clone(); } catch (CloneNotSupportedException e) { - throw new GraalInternalError(e).addContext(this); + throw new GraalGraphInternalError(e).addContext(this); } if (clearInputsAndSuccessors) { nodeClass.clearInputs(newNode); diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.graph/src/com/oracle/graal/graph/NodeBitMap.java --- a/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/NodeBitMap.java Fri Apr 25 16:21:07 2014 +0200 +++ b/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/NodeBitMap.java Mon Apr 28 11:18:15 2014 +0200 @@ -26,7 +26,7 @@ import com.oracle.graal.graph.iterators.*; -public final class NodeBitMap extends AbstractNodeIterable { +public final class NodeBitMap implements NodeIterable { private final boolean autoGrow; private final BitSet bitMap; diff -r 3dde8d8c95b8 -r 40d0022115ee 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 Fri Apr 25 16:21:07 2014 +0200 +++ b/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/NodeClass.java Mon Apr 28 11:18:15 2014 +0200 @@ -26,8 +26,8 @@ import java.lang.reflect.*; import java.util.*; -import java.util.concurrent.*; +import com.oracle.graal.compiler.common.*; import com.oracle.graal.debug.*; import com.oracle.graal.graph.Graph.DuplicationReplacement; import com.oracle.graal.graph.Node.Input; @@ -36,7 +36,7 @@ import com.oracle.graal.graph.spi.*; /** - * Lazily associated metadata for every {@link Node} type. The metadata includes: + * Metadata for every {@link Node} type. The metadata includes: *
    *
  • The offsets of fields annotated with {@link Input} and {@link Successor} as well as methods * for iterating over such fields.
  • @@ -45,72 +45,7 @@ */ public final class NodeClass extends FieldIntrospection { - /** - * Maps {@link Class} values (for {@link Node} types) to {@link NodeClass} values. - * - * Only a single Registry instance can be created. If a runtime creates a specialized registry, - * it must do so before the class initializer of {@link NodeClass} is executed. - */ - public static class Registry { - - private static Registry instance; - - /** - * Gets the singleton {@link Registry} instance, creating it first if necessary. - */ - static synchronized Registry instance() { - if (instance == null) { - return new Registry(); - } - return instance; - } - - protected Registry() { - assert instance == null : "exactly one registry can be created"; - instance = this; - } - - /** - * @return the {@link NodeClass} value for {@code key} or {@code null} if no such mapping - * exists - */ - protected NodeClass get(Class key) { - return (NodeClass) allClasses.get(key); - } - - /** - * Same as {@link #get(Class)} except that a {@link NodeClass} is created if no such mapping - * exists. The creation of a {@link NodeClass} must be serialized as - * {@link NodeClass#NodeClass(Class)} accesses both {@link FieldIntrospection#allClasses} - * and {@link NodeClass#nextIterableId}. - *

    - * The fact that {@link ConcurrentHashMap#put} {@link ConcurrentHashMap#get} are used should - * make the double-checked locking idiom work in the way {@link NodeClass#get(Class)} uses - * this method and {@link #get(Class)}. - */ - final synchronized NodeClass make(Class key) { - NodeClass value = (NodeClass) allClasses.get(key); - if (value == null) { - value = new NodeClass(key); - Object old = allClasses.putIfAbsent(key, value); - assert old == null; - registered(key, value); - } - return value; - } - - /** - * Hook for a subclass to be notified of a new mapping added to the registry. - * - * @param key - * @param value - */ - protected void registered(Class key, NodeClass value) { - - } - } - - private static final Registry registry = Registry.instance(); + private static final Object GetNodeClassLock = new Object(); /** * Gets the {@link NodeClass} associated with a given {@link Class}. @@ -118,11 +53,22 @@ @SuppressWarnings("unchecked") public static NodeClass get(Class c) { Class key = (Class) c; - NodeClass value = registry.get(key); - if (value != null) { - return value; + NodeClass value = (NodeClass) allClasses.get(key); + // The fact that {@link ConcurrentHashMap#put} and {@link ConcurrentHashMap#get} + // are used makes the double-checked locking idiom work. + if (value == null) { + // The creation of a NodeClass must be serialized as the NodeClass constructor accesses + // both FieldIntrospection.allClasses and NodeClass.nextIterableId. + synchronized (GetNodeClassLock) { + value = (NodeClass) allClasses.get(key); + if (value == null) { + value = new NodeClass(key); + Object old = allClasses.putIfAbsent(key, value); + assert old == null : old + " " + key; + } + } } - return registry.make(key); + return value; } public static final int NOT_ITERABLE = -1; @@ -137,10 +83,8 @@ private final int directInputCount; private final long[] inputOffsets; private final InputType[] inputTypes; - private final String[] inputNames; private final int directSuccessorCount; private final long[] successorOffsets; - private final String[] successorNames; private final Class[] dataTypes; private final boolean canGVN; private final boolean isLeafNode; @@ -180,20 +124,12 @@ directInputCount = scanner.inputOffsets.size(); inputOffsets = sortedLongCopy(scanner.inputOffsets, scanner.inputListOffsets); inputTypes = new InputType[inputOffsets.length]; - inputNames = new String[inputOffsets.length]; for (int i = 0; i < inputOffsets.length; i++) { inputTypes[i] = scanner.types.get(inputOffsets[i]); - inputNames[i] = scanner.names.get(inputOffsets[i]); assert inputTypes[i] != null; - assert inputNames[i] != null; } directSuccessorCount = scanner.successorOffsets.size(); successorOffsets = sortedLongCopy(scanner.successorOffsets, scanner.successorListOffsets); - successorNames = new String[successorOffsets.length]; - for (int i = 0; i < successorOffsets.length; i++) { - successorNames[i] = scanner.names.get(successorOffsets[i]); - assert successorNames[i] != null; - } dataOffsets = sortedLongCopy(scanner.dataOffsets); dataTypes = new Class[dataOffsets.length]; @@ -243,10 +179,10 @@ this.iterableId = nextIterableId++; List existingClasses = new LinkedList<>(); for (FieldIntrospection nodeClass : allClasses.values()) { - if (clazz.isAssignableFrom(nodeClass.clazz)) { + if (clazz.isAssignableFrom(nodeClass.getClazz())) { existingClasses.add((NodeClass) nodeClass); } - if (nodeClass.clazz.isAssignableFrom(clazz) && IterableNodeType.class.isAssignableFrom(nodeClass.clazz)) { + if (nodeClass.getClazz().isAssignableFrom(clazz) && IterableNodeType.class.isAssignableFrom(nodeClass.getClazz())) { NodeClass superNodeClass = (NodeClass) nodeClass; superNodeClass.iterableIds = Arrays.copyOf(superNodeClass.iterableIds, superNodeClass.iterableIds.length + 1); superNodeClass.iterableIds[superNodeClass.iterableIds.length - 1] = this.iterableId; @@ -271,7 +207,7 @@ @Override protected void rescanFieldOffsets(CalcOffset calc) { FieldScanner scanner = new FieldScanner(calc); - scanner.scan(clazz); + scanner.scan(getClazz()); assert directInputCount == scanner.inputOffsets.size(); copyInto(inputOffsets, sortedLongCopy(scanner.inputOffsets, scanner.inputListOffsets)); assert directSuccessorCount == scanner.successorOffsets.size(); @@ -388,7 +324,7 @@ @Override public String toString() { StringBuilder str = new StringBuilder(); - str.append("NodeClass ").append(clazz.getSimpleName()).append(" ["); + str.append("NodeClass ").append(getClazz().getSimpleName()).append(" ["); for (int i = 0; i < inputOffsets.length; i++) { str.append(i == 0 ? "" : ", ").append(inputOffsets[i]); } @@ -412,9 +348,9 @@ */ public static final class Position { - public final boolean input; - public final int index; - public final int subIndex; + private final boolean input; + private final int index; + private final int subIndex; public Position(boolean input, int index, int subIndex) { this.input = input; @@ -436,7 +372,7 @@ } public String getInputName(Node node) { - return node.getNodeClass().getEdgeName(this); + return node.getNodeClass().getName(this); } public void set(Node node, Node value) { @@ -480,6 +416,18 @@ } return true; } + + public int getSubIndex() { + return subIndex; + } + + public int getIndex() { + return index; + } + + public boolean isInput() { + return input; + } } private static Node getNode(Node node, long offset) { @@ -871,7 +819,7 @@ } public boolean valueEqual(Node a, Node b) { - if (!canGVN || a.getClass() != b.getClass()) { + if (a.getClass() != b.getClass()) { return a == b; } for (int i = 0; i < dataOffsets.length; ++i) { @@ -949,43 +897,39 @@ if (this == from) { return true; } - long[] offsets = pos.input ? inputOffsets : successorOffsets; - if (pos.index >= offsets.length) { + long[] offsets = pos.isInput() ? inputOffsets : successorOffsets; + if (pos.getIndex() >= offsets.length) { return false; } - long[] fromOffsets = pos.input ? from.inputOffsets : from.successorOffsets; - if (pos.index >= fromOffsets.length) { + long[] fromOffsets = pos.isInput() ? from.inputOffsets : from.successorOffsets; + if (pos.getIndex() >= fromOffsets.length) { return false; } - return offsets[pos.index] == fromOffsets[pos.index]; + return offsets[pos.getIndex()] == fromOffsets[pos.getIndex()]; } public Node get(Node node, Position pos) { - long offset = pos.input ? inputOffsets[pos.index] : successorOffsets[pos.index]; - if (pos.subIndex == NOT_ITERABLE) { + long offset = pos.isInput() ? inputOffsets[pos.getIndex()] : successorOffsets[pos.getIndex()]; + if (pos.getSubIndex() == NOT_ITERABLE) { return getNode(node, offset); } else { - return getNodeList(node, offset).get(pos.subIndex); + return getNodeList(node, offset).get(pos.getSubIndex()); } } public InputType getInputType(Position pos) { - assert pos.input; - return inputTypes[pos.index]; - } - - public String getEdgeName(Position pos) { - return pos.input ? inputNames[pos.index] : successorNames[pos.index]; + assert pos.isInput(); + return inputTypes[pos.getIndex()]; } public NodeList getNodeList(Node node, Position pos) { - long offset = pos.input ? inputOffsets[pos.index] : successorOffsets[pos.index]; - assert pos.subIndex == NODE_LIST; + long offset = pos.isInput() ? inputOffsets[pos.getIndex()] : successorOffsets[pos.getIndex()]; + assert pos.getSubIndex() == NODE_LIST; return getNodeList(node, offset); } public String getName(Position pos) { - return fieldNames.get(pos.input ? inputOffsets[pos.index] : successorOffsets[pos.index]); + return fieldNames.get(pos.isInput() ? inputOffsets[pos.getIndex()] : successorOffsets[pos.getIndex()]); } void updateInputSuccInPlace(Node node, InplaceUpdateClosure duplicationReplacement) { @@ -1028,7 +972,7 @@ int index = startIndex; while (index < inputOffsets.length) { NodeList list = getNodeList(node, inputOffsets[index]); - assert list != null : clazz; + assert list != null : getClazz(); putNodeList(node, inputOffsets[index], updateInputListCopy(list, node, duplicationReplacement)); index++; } @@ -1038,7 +982,7 @@ int index = startIndex; while (index < successorOffsets.length) { NodeList list = getNodeList(node, successorOffsets[index]); - assert list != null : clazz; + assert list != null : getClazz(); putNodeList(node, successorOffsets[index], updateSuccListCopy(list, node, duplicationReplacement)); index++; } @@ -1071,22 +1015,22 @@ } public void set(Node node, Position pos, Node x) { - long offset = pos.input ? inputOffsets[pos.index] : successorOffsets[pos.index]; - if (pos.subIndex == NOT_ITERABLE) { + long offset = pos.isInput() ? inputOffsets[pos.getIndex()] : successorOffsets[pos.getIndex()]; + if (pos.getSubIndex() == NOT_ITERABLE) { Node old = getNode(node, offset); - assert x == null || fieldTypes.get((pos.input ? inputOffsets : successorOffsets)[pos.index]).isAssignableFrom(x.getClass()) : this + ".set(node, pos, " + x + ")"; + assert x == null || fieldTypes.get((pos.isInput() ? inputOffsets : successorOffsets)[pos.getIndex()]).isAssignableFrom(x.getClass()) : this + ".set(node, pos, " + x + ")"; putNode(node, offset, x); - if (pos.input) { + if (pos.isInput()) { node.updateUsages(old, x); } else { node.updatePredecessor(old, x); } } else { NodeList list = getNodeList(node, offset); - if (pos.subIndex < list.size()) { - list.set(pos.subIndex, x); + if (pos.getSubIndex() < list.size()) { + list.set(pos.getSubIndex(), x); } else { - while (pos.subIndex < list.size() - 1) { + while (pos.getSubIndex() < list.size() - 1) { list.add(null); } list.add(x); @@ -1095,7 +1039,7 @@ } public NodeClassIterable getInputIterable(final Node node) { - assert clazz.isInstance(node); + assert getClazz().isInstance(node); return new NodeClassIterable() { @Override @@ -1115,7 +1059,7 @@ } public NodeClassIterable getSuccessorIterable(final Node node) { - assert clazz.isInstance(node); + assert getClazz().isInstance(node); return new NodeClassIterable() { @Override @@ -1148,7 +1092,7 @@ } while (index < inputOffsets.length) { NodeList list = getNodeList(node, inputOffsets[index]); - assert list != null : clazz; + assert list != null : getClazz(); if (list.replaceFirst(old, other)) { return true; } @@ -1171,7 +1115,7 @@ } while (index < successorOffsets.length) { NodeList list = getNodeList(node, successorOffsets[index]); - assert list != null : clazz + " " + successorOffsets[index] + " " + node; + assert list != null : getClazz() + " " + successorOffsets[index] + " " + node; if (list.replaceFirst(old, other)) { return true; } @@ -1228,7 +1172,7 @@ * @param newNode the node to which the inputs should be copied. */ public void copyInputs(Node node, Node newNode) { - assert node.getClass() == clazz && newNode.getClass() == clazz; + assert node.getClass() == getClazz() && newNode.getClass() == getClazz(); int index = 0; while (index < directInputCount) { @@ -1250,7 +1194,7 @@ * @param newNode the node to which the successors should be copied. */ public void copySuccessors(Node node, Node newNode) { - assert node.getClass() == clazz && newNode.getClass() == clazz; + assert node.getClass() == getClazz() && newNode.getClass() == getClazz(); int index = 0; while (index < directSuccessorCount) { @@ -1269,7 +1213,7 @@ } public boolean inputsEqual(Node node, Node other) { - assert node.getClass() == clazz && other.getClass() == clazz; + assert node.getClass() == getClazz() && other.getClass() == getClazz(); int index = 0; while (index < directInputCount) { if (getNode(other, inputOffsets[index]) != getNode(node, inputOffsets[index])) { @@ -1288,7 +1232,7 @@ } public boolean successorsEqual(Node node, Node other) { - assert node.getClass() == clazz && other.getClass() == clazz; + assert node.getClass() == getClazz() && other.getClass() == getClazz(); int index = 0; while (index < directSuccessorCount) { if (getNode(other, successorOffsets[index]) != getNode(node, successorOffsets[index])) { @@ -1307,7 +1251,7 @@ } public boolean inputContains(Node node, Node other) { - assert node.getClass() == clazz; + assert node.getClass() == getClazz(); int index = 0; while (index < directInputCount) { @@ -1327,7 +1271,7 @@ } public boolean successorContains(Node node, Node other) { - assert node.getClass() == clazz; + assert node.getClass() == getClazz(); int index = 0; while (index < directSuccessorCount) { @@ -1409,7 +1353,7 @@ } public Class getJavaClass() { - return clazz; + return getClazz(); } /** @@ -1509,7 +1453,7 @@ replacement = replacements.replacement(input); } if (replacement != input) { - assert isAssignable(nodeClass.fieldTypes.get(nodeClass.inputOffsets[pos.index]), replacement); + assert isAssignable(nodeClass.fieldTypes.get(nodeClass.inputOffsets[pos.getIndex()]), replacement); target = replacement; } else if (input.graph() == graph) { // patch to the outer world target = input; @@ -1528,7 +1472,7 @@ if (target == null) { Node replacement = replacements.replacement(succ); if (replacement != succ) { - assert isAssignable(nodeClass.fieldTypes.get(node.getNodeClass().successorOffsets[pos.index]), replacement); + assert isAssignable(nodeClass.fieldTypes.get(node.getNodeClass().successorOffsets[pos.getIndex()]), replacement); target = replacement; } } diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.graph/src/com/oracle/graal/graph/NodeClassIterable.java --- a/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/NodeClassIterable.java Fri Apr 25 16:21:07 2014 +0200 +++ b/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/NodeClassIterable.java Mon Apr 28 11:18:15 2014 +0200 @@ -30,7 +30,7 @@ * The iterator returned by this iterable can be used to access {@link Position Positions} during * iteration using {@link NodeClassIterator#nextPosition()}. */ -public abstract class NodeClassIterable extends AbstractNodeIterable { +public interface NodeClassIterable extends NodeIterable { @Override public abstract NodeClassIterator iterator(); diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.graph/src/com/oracle/graal/graph/NodeList.java --- a/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/NodeList.java Fri Apr 25 16:21:07 2014 +0200 +++ b/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/NodeList.java Mon Apr 28 11:18:15 2014 +0200 @@ -257,7 +257,7 @@ } @Override - public void snapshotTo(Collection to) { + public void snapshotTo(Collection to) { for (int i = 0; i < size; i++) { to.add(get(i)); } @@ -348,42 +348,6 @@ } @Override - public NodeIterable until(final T u) { - return new FilteredNodeIterable<>(this).until(u); - } - - @Override - public NodeIterable until(final Class clazz) { - return new FilteredNodeIterable<>(this).until(clazz); - } - - @Override - @SuppressWarnings("unchecked") - public NodeIterable filter(Class clazz) { - return (NodeIterable) new FilteredNodeIterable<>(this).and(NodePredicates.isA(clazz)); - } - - @Override - public NodeIterable filterInterface(Class iface) { - return new FilteredNodeIterable<>(this).and(NodePredicates.isAInterface(iface)); - } - - @Override - public FilteredNodeIterable filter(NodePredicate predicate) { - return new FilteredNodeIterable<>(this).and(predicate); - } - - @Override - public FilteredNodeIterable nonNull() { - return new FilteredNodeIterable<>(this).and(NodePredicates.isNotNull()); - } - - @Override - public NodeIterable distinct() { - return new FilteredNodeIterable<>(this).distinct(); - } - - @Override public T first() { if (size() > 0) { return get(0); diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.graph/src/com/oracle/graal/graph/UnsafeAccess.java --- a/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/UnsafeAccess.java Fri Apr 25 16:21:07 2014 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,102 +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.graph; - -import java.lang.reflect.*; - -import sun.misc.*; - -public class UnsafeAccess { - - /** - * An instance of {@link Unsafe} for use within Graal. - */ - public static final Unsafe unsafe = getUnsafe(); - - private static Unsafe getUnsafe() { - try { - // this will fail if Graal is not part of the boot class path - return Unsafe.getUnsafe(); - } catch (SecurityException e) { - // nothing to do - } - try { - Field theUnsafeInstance = Unsafe.class.getDeclaredField("theUnsafe"); - theUnsafeInstance.setAccessible(true); - return (Unsafe) theUnsafeInstance.get(Unsafe.class); - } catch (Exception e) { - // currently we rely on being able to use Unsafe... - throw new RuntimeException("exception while trying to get Unsafe.theUnsafe via reflection:", e); - } - } - - /** - * Copies the contents of a {@link String} to a native memory buffer as a {@code '\0'} - * terminated C string. The native memory buffer is allocated via - * {@link Unsafe#allocateMemory(long)}. The caller is responsible for releasing the buffer when - * it is no longer needed via {@link Unsafe#freeMemory(long)}. - * - * @return the native memory pointer of the C string created from {@code s} - */ - public static long createCString(String s) { - return writeCString(s, unsafe.allocateMemory(s.length() + 1)); - } - - /** - * Reads a {@code '\0'} terminated C string from native memory and converts it to a - * {@link String}. - * - * @return a Java string - */ - public static String readCString(long address) { - if (address == 0) { - return null; - } - StringBuffer sb = new StringBuffer(); - for (int i = 0;; i++) { - char c = (char) unsafe.getByte(address + i); - if (c == 0) { - break; - } - sb.append(c); - } - return sb.toString(); - } - - /** - * Writes the contents of a {@link String} to a native memory buffer as a {@code '\0'} - * terminated C string. The caller is responsible for ensuring the buffer is at least - * {@code s.length() + 1} bytes long. The caller is also responsible for releasing the buffer - * when it is no longer. - * - * @return the value of {@code buf} - */ - public static long writeCString(String s, long buf) { - int size = s.length(); - for (int i = 0; i < size; i++) { - unsafe.putByte(buf + i, (byte) s.charAt(i)); - } - unsafe.putByte(buf + size, (byte) '\0'); - return buf; - } -} diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.graph/src/com/oracle/graal/graph/VerificationError.java --- a/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/VerificationError.java Fri Apr 25 16:21:07 2014 +0200 +++ b/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/VerificationError.java Mon Apr 28 11:18:15 2014 +0200 @@ -26,7 +26,7 @@ * This error represents a failed verification of a node . It must only be used for conditions that * should never occur during normal operation. */ -public class VerificationError extends GraalInternalError { +public class VerificationError extends GraalGraphInternalError { private static final long serialVersionUID = 8459607567446819822L; diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.graph/src/com/oracle/graal/graph/iterators/AbstractNodeIterable.java --- a/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/iterators/AbstractNodeIterable.java Fri Apr 25 16:21:07 2014 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,117 +0,0 @@ -/* - * Copyright (c) 2011, 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.graph.iterators; - -import java.util.*; - -import com.oracle.graal.graph.*; - -public abstract class AbstractNodeIterable implements NodeIterable { - - @Override - public NodeIterable until(final T u) { - return new FilteredNodeIterable<>(this).until(u); - } - - @Override - public NodeIterable until(final Class clazz) { - return new FilteredNodeIterable<>(this).until(clazz); - } - - @Override - @SuppressWarnings("unchecked") - public NodeIterable filter(Class clazz) { - return (NodeIterable) new FilteredNodeIterable<>(this).and(NodePredicates.isA(clazz)); - } - - @Override - public NodeIterable filterInterface(Class iface) { - return new FilteredNodeIterable<>(this).and(NodePredicates.isAInterface(iface)); - } - - @Override - public FilteredNodeIterable filter(NodePredicate predicate) { - return new FilteredNodeIterable<>(this).and(predicate); - } - - @Override - public FilteredNodeIterable nonNull() { - return new FilteredNodeIterable<>(this).and(NodePredicates.isNotNull()); - } - - @Override - public NodeIterable distinct() { - return new FilteredNodeIterable<>(this).distinct(); - } - - @Override - public List snapshot() { - ArrayList list = new ArrayList<>(); - for (T n : this) { - list.add(n); - } - return list; - } - - @Override - public void snapshotTo(Collection to) { - for (T n : this) { - to.add(n); - } - } - - @Override - public T first() { - Iterator iterator = iterator(); - if (iterator.hasNext()) { - return iterator.next(); - } - return null; - } - - @Override - public int count() { - int count = 0; - Iterator iterator = iterator(); - while (iterator.hasNext()) { - iterator.next(); - count++; - } - return count; - } - - @Override - public boolean isEmpty() { - return !iterator().hasNext(); - } - - @Override - public boolean isNotEmpty() { - return iterator().hasNext(); - } - - @Override - public boolean contains(T node) { - return this.filter(NodePredicates.equals(node)).isNotEmpty(); - } -} diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.graph/src/com/oracle/graal/graph/iterators/DistinctFilteredNodeIterable.java --- a/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/iterators/DistinctFilteredNodeIterable.java Fri Apr 25 16:21:07 2014 +0200 +++ b/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/iterators/DistinctFilteredNodeIterable.java Mon Apr 28 11:18:15 2014 +0200 @@ -39,6 +39,6 @@ @Override public Iterator iterator() { - return new DistinctPredicatedProxyNodeIterator<>(until, nodeIterable.iterator(), predicate); + return new DistinctPredicatedProxyNodeIterator<>(nodeIterable.iterator(), predicate); } } diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.graph/src/com/oracle/graal/graph/iterators/DistinctPredicatedProxyNodeIterator.java --- a/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/iterators/DistinctPredicatedProxyNodeIterator.java Fri Apr 25 16:21:07 2014 +0200 +++ b/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/iterators/DistinctPredicatedProxyNodeIterator.java Mon Apr 28 11:18:15 2014 +0200 @@ -30,8 +30,8 @@ private NodeBitMap visited; - public DistinctPredicatedProxyNodeIterator(NodePredicate until, Iterator iterator, NodePredicate predicate) { - super(until, iterator, predicate); + public DistinctPredicatedProxyNodeIterator(Iterator iterator, NodePredicate predicate) { + super(iterator, predicate); } @Override diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.graph/src/com/oracle/graal/graph/iterators/FilteredNodeIterable.java --- a/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/iterators/FilteredNodeIterable.java Fri Apr 25 16:21:07 2014 +0200 +++ b/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/iterators/FilteredNodeIterable.java Mon Apr 28 11:18:15 2014 +0200 @@ -26,11 +26,10 @@ import com.oracle.graal.graph.*; -public class FilteredNodeIterable extends AbstractNodeIterable { +public class FilteredNodeIterable implements NodeIterable { protected final NodeIterable nodeIterable; protected NodePredicate predicate = NodePredicates.alwaysTrue(); - protected NodePredicate until = NodePredicates.isNull(); public FilteredNodeIterable(NodeIterable nodeIterable) { this.nodeIterable = nodeIterable; @@ -47,18 +46,6 @@ } @Override - public NodeIterable until(final T u) { - until = until.or(NodePredicates.equals(u)); - return this; - } - - @Override - public NodeIterable until(final Class clazz) { - until = until.or(NodePredicates.isA(clazz)); - return this; - } - - @Override public FilteredNodeIterable nonNull() { this.predicate = this.predicate.and(NodePredicates.isNotNull()); return this; @@ -68,13 +55,12 @@ public DistinctFilteredNodeIterable distinct() { DistinctFilteredNodeIterable distinct = new DistinctFilteredNodeIterable<>(nodeIterable); distinct.predicate = predicate; - distinct.until = until; return distinct; } @Override public Iterator iterator() { - return new PredicatedProxyNodeIterator<>(until, nodeIterable.iterator(), predicate); + return new PredicatedProxyNodeIterator<>(nodeIterable.iterator(), predicate); } @SuppressWarnings("unchecked") diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.graph/src/com/oracle/graal/graph/iterators/NodeIterable.java --- a/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/iterators/NodeIterable.java Fri Apr 25 16:21:07 2014 +0200 +++ b/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/iterators/NodeIterable.java Mon Apr 28 11:18:15 2014 +0200 @@ -28,32 +28,66 @@ public interface NodeIterable extends Iterable { - NodeIterable until(T u); + @SuppressWarnings("unchecked") + default NodeIterable filter(Class clazz) { + return (NodeIterable) new FilteredNodeIterable<>(this).and(NodePredicates.isA(clazz)); + } - NodeIterable until(Class clazz); + default NodeIterable filterInterface(Class iface) { + return new FilteredNodeIterable<>(this).and(NodePredicates.isAInterface(iface)); + } - NodeIterable filter(Class clazz); + default FilteredNodeIterable filter(NodePredicate predicate) { + return new FilteredNodeIterable<>(this).and(predicate); + } - NodeIterable filterInterface(Class iface); - - FilteredNodeIterable filter(NodePredicate predicate); + default FilteredNodeIterable nonNull() { + return new FilteredNodeIterable<>(this).and(NodePredicates.isNotNull()); + } - FilteredNodeIterable nonNull(); + default NodeIterable distinct() { + return new FilteredNodeIterable<>(this).distinct(); + } - NodeIterable distinct(); + default List snapshot() { + ArrayList list = new ArrayList<>(); + snapshotTo(list); + return list; + } - List snapshot(); - - void snapshotTo(Collection to); + default void snapshotTo(Collection to) { + for (T n : this) { + to.add(n); + } + } - T first(); - - int count(); + default T first() { + Iterator iterator = iterator(); + if (iterator.hasNext()) { + return iterator.next(); + } + return null; + } - boolean isEmpty(); - - boolean isNotEmpty(); + default int count() { + int count = 0; + Iterator iterator = iterator(); + while (iterator.hasNext()) { + iterator.next(); + count++; + } + return count; + } - boolean contains(T node); + default boolean isEmpty() { + return !iterator().hasNext(); + } + default boolean isNotEmpty() { + return iterator().hasNext(); + } + + default boolean contains(T node) { + return this.filter(NodePredicates.equals(node)).isNotEmpty(); + } } diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.graph/src/com/oracle/graal/graph/iterators/NodePredicate.java --- a/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/iterators/NodePredicate.java Fri Apr 25 16:21:07 2014 +0200 +++ b/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/iterators/NodePredicate.java Mon Apr 28 11:18:15 2014 +0200 @@ -23,20 +23,21 @@ package com.oracle.graal.graph.iterators; import com.oracle.graal.graph.*; +import com.oracle.graal.graph.iterators.NodePredicates.*; -public abstract class NodePredicate { +public interface NodePredicate { - public abstract boolean apply(Node n); + boolean apply(Node n); - public NodePredicate and(NodePredicate np) { - return NodePredicates.and(this, np); + default NodePredicate and(NodePredicate np) { + return new AndPredicate(this, np); } - public NodePredicate or(NodePredicate np) { - return NodePredicates.or(this, np); + default NodePredicate or(NodePredicate np) { + return new OrPredicate(this, np); } - public NodePredicate negate() { - return NodePredicates.not(this); + default NodePredicate negate() { + return new NotPredicate(this); } } diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.graph/src/com/oracle/graal/graph/iterators/NodePredicates.java --- a/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/iterators/NodePredicates.java Fri Apr 25 16:21:07 2014 +0200 +++ b/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/iterators/NodePredicates.java Mon Apr 28 11:18:15 2014 +0200 @@ -27,7 +27,7 @@ public abstract class NodePredicates { private static final TautologyPredicate TAUTOLOGY = new TautologyPredicate(); - private static final FalsePredicate FALSE = new FalsePredicate(); + private static final ContradictionPredicate CONTRADICTION = new ContradictionPredicate(); private static final IsNullPredicate IS_NULL = new IsNullPredicate(); private static final IsNotNullPredicate IS_NOT_NULL = new IsNotNullPredicate(); @@ -36,7 +36,7 @@ } public static NodePredicate alwaysFalse() { - return FALSE; + return CONTRADICTION; } public static NodePredicate isNull() { @@ -52,60 +52,7 @@ } public static NodePredicate not(NodePredicate a) { - if (a == TAUTOLOGY) { - return FALSE; - } - if (a == FALSE) { - return TAUTOLOGY; - } - if (a == IS_NULL) { - return IS_NOT_NULL; - } - if (a == IS_NOT_NULL) { - return IS_NULL; - } - if (a instanceof NotPredicate) { - return ((NotPredicate) a).a; - } - if (a instanceof PositiveTypePredicate) { - return new NegativeTypePredicate((PositiveTypePredicate) a); - } - if (a instanceof NegativeTypePredicate) { - return new PositiveTypePredicate((NegativeTypePredicate) a); - } - if (a instanceof EqualsPredicate) { - return new NotEqualsPredicate(((EqualsPredicate) a).u); - } - if (a instanceof NotEqualsPredicate) { - return new EqualsPredicate(((NotEqualsPredicate) a).u); - } - return new NotPredicate(a); - } - - public static NodePredicate and(NodePredicate a, NodePredicate b) { - if (a == TAUTOLOGY) { - return b; - } - if (b == TAUTOLOGY) { - return a; - } - if (a == FALSE || b == FALSE) { - return FALSE; - } - return new AndPredicate(a, b); - } - - public static NodePredicate or(NodePredicate a, NodePredicate b) { - if (a == FALSE) { - return b; - } - if (b == FALSE) { - return a; - } - if (a == TAUTOLOGY || b == TAUTOLOGY) { - return TAUTOLOGY; - } - return new OrPredicate(a, b); + return a.negate(); } public static NegativeTypePredicate isNotA(Class clazz) { @@ -126,28 +73,52 @@ return new NegativeTypePredicate(iface); } - private static final class TautologyPredicate extends NodePredicate { + static final class TautologyPredicate implements NodePredicate { @Override public boolean apply(Node n) { return true; } + + public NodePredicate and(NodePredicate np) { + return np; + } + + public NodePredicate negate() { + return CONTRADICTION; + } + + public NodePredicate or(NodePredicate np) { + return this; + } } - private static final class FalsePredicate extends NodePredicate { + static final class ContradictionPredicate implements NodePredicate { @Override public boolean apply(Node n) { return false; } + + public NodePredicate and(NodePredicate np) { + return this; + } + + public NodePredicate negate() { + return TAUTOLOGY; + } + + public NodePredicate or(NodePredicate np) { + return np; + } } - private static final class AndPredicate extends NodePredicate { + static final class AndPredicate implements NodePredicate { private final NodePredicate a; private final NodePredicate b; - private AndPredicate(NodePredicate a, NodePredicate b) { + AndPredicate(NodePredicate a, NodePredicate b) { this.a = a; this.b = b; } @@ -158,11 +129,11 @@ } } - private static final class NotPredicate extends NodePredicate { + static final class NotPredicate implements NodePredicate { private final NodePredicate a; - private NotPredicate(NodePredicate n) { + NotPredicate(NodePredicate n) { this.a = n; } @@ -170,14 +141,18 @@ public boolean apply(Node n) { return !a.apply(n); } + + public NodePredicate negate() { + return a; + } } - private static final class OrPredicate extends NodePredicate { + static final class OrPredicate implements NodePredicate { private final NodePredicate a; private final NodePredicate b; - private OrPredicate(NodePredicate a, NodePredicate b) { + OrPredicate(NodePredicate a, NodePredicate b) { this.a = a; this.b = b; } @@ -188,27 +163,35 @@ } } - private static final class IsNullPredicate extends NodePredicate { + static final class IsNullPredicate implements NodePredicate { @Override public boolean apply(Node n) { return n == null; } + + public NodePredicate negate() { + return IS_NOT_NULL; + } } - private static final class IsNotNullPredicate extends NodePredicate { + static final class IsNotNullPredicate implements NodePredicate { @Override public boolean apply(Node n) { return n != null; } + + public NodePredicate negate() { + return IS_NULL; + } } - private static final class EqualsPredicate extends NodePredicate { + static final class EqualsPredicate implements NodePredicate { private final Node u; - public EqualsPredicate(Node u) { + EqualsPredicate(Node u) { this.u = u; } @@ -216,13 +199,17 @@ public boolean apply(Node n) { return u == n; } + + public NodePredicate negate() { + return new NotEqualsPredicate(u); + } } - private static final class NotEqualsPredicate extends NodePredicate { + static final class NotEqualsPredicate implements NodePredicate { private final Node u; - public NotEqualsPredicate(Node u) { + NotEqualsPredicate(Node u) { this.u = u; } @@ -230,14 +217,18 @@ public boolean apply(Node n) { return u != n; } + + public NodePredicate negate() { + return new EqualsPredicate(u); + } } - public static final class PositiveTypePredicate extends NodePredicate { + public static final class PositiveTypePredicate implements NodePredicate { private final Class type; private PositiveTypePredicate or; - public PositiveTypePredicate(Class type) { + PositiveTypePredicate(Class type) { this.type = type; } @@ -261,14 +252,18 @@ } return this; } + + public NodePredicate negate() { + return new NegativeTypePredicate(this); + } } - public static final class NegativeTypePredicate extends NodePredicate { + public static final class NegativeTypePredicate implements NodePredicate { private final Class type; private NegativeTypePredicate nor; - public NegativeTypePredicate(Class type) { + NegativeTypePredicate(Class type) { this.type = type; } @@ -292,5 +287,9 @@ } return this; } + + public NodePredicate negate() { + return new PositiveTypePredicate(this); + } } } diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.graph/src/com/oracle/graal/graph/iterators/PredicatedProxyNodeIterator.java --- a/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/iterators/PredicatedProxyNodeIterator.java Fri Apr 25 16:21:07 2014 +0200 +++ b/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/iterators/PredicatedProxyNodeIterator.java Mon Apr 28 11:18:15 2014 +0200 @@ -30,10 +30,8 @@ private final Iterator iterator; private final NodePredicate predicate; - private final NodePredicate until; - public PredicatedProxyNodeIterator(NodePredicate until, Iterator iterator, NodePredicate predicate) { - this.until = until; + public PredicatedProxyNodeIterator(Iterator iterator, NodePredicate predicate) { this.iterator = iterator; this.predicate = predicate; } @@ -43,7 +41,7 @@ while ((current == null || !current.isAlive() || !predicate.apply(current)) && iterator.hasNext()) { current = iterator.next(); } - if (current != null && (!current.isAlive() || !predicate.apply(current) || until.apply(current))) { + if (current != null && (!current.isAlive() || !predicate.apply(current))) { current = null; } } diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64DeoptimizationStub.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64DeoptimizationStub.java Mon Apr 28 11:18:15 2014 +0200 @@ -0,0 +1,45 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.graal.hotspot.amd64; + +import static com.oracle.graal.amd64.AMD64.*; + +import com.oracle.graal.api.code.*; +import com.oracle.graal.hotspot.*; +import com.oracle.graal.hotspot.meta.*; +import com.oracle.graal.hotspot.stubs.*; + +final class AMD64DeoptimizationStub extends DeoptimizationStub { + + private RegisterConfig registerConfig; + + public AMD64DeoptimizationStub(HotSpotProviders providers, TargetDescription target, HotSpotForeignCallLinkage linkage) { + super(providers, target, linkage); + registerConfig = new AMD64HotSpotRegisterConfig(target.arch, HotSpotGraalRuntime.runtime().getConfig(), new Register[]{rax, rbx, rcx, rdx, rsi, rdi, r8, r9, r10, r11, r13, r14}); + } + + @Override + public RegisterConfig getRegisterConfig() { + return registerConfig; + } +} diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64DeoptimizeOp.java --- a/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64DeoptimizeOp.java Fri Apr 25 16:21:07 2014 +0200 +++ b/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64DeoptimizeOp.java Mon Apr 28 11:18:15 2014 +0200 @@ -41,6 +41,6 @@ @Override public void emitCode(CompilationResultBuilder crb, AMD64MacroAssembler masm) { - AMD64Call.directCall(crb, masm, crb.foreignCalls.lookupForeignCall(UNCOMMON_TRAP), null, false, info); + AMD64Call.directCall(crb, masm, crb.foreignCalls.lookupForeignCall(UNCOMMON_TRAP_HANDLER), null, false, info); } } diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotBackend.java --- a/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotBackend.java Fri Apr 25 16:21:07 2014 +0200 +++ b/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotBackend.java Mon Apr 28 11:18:15 2014 +0200 @@ -25,9 +25,7 @@ import static com.oracle.graal.amd64.AMD64.*; import static com.oracle.graal.api.code.CallingConvention.Type.*; import static com.oracle.graal.api.code.ValueUtil.*; -import static com.oracle.graal.phases.GraalOptions.*; -import static java.lang.reflect.Modifier.*; - +import static com.oracle.graal.compiler.common.GraalOptions.*; import java.util.*; import sun.misc.*; @@ -48,7 +46,9 @@ import com.oracle.graal.lir.*; import com.oracle.graal.lir.amd64.*; import com.oracle.graal.lir.asm.*; +import com.oracle.graal.lir.gen.*; import com.oracle.graal.nodes.*; +import com.oracle.graal.nodes.spi.*; /** * HotSpot AMD64 specific backend. @@ -72,7 +72,7 @@ } @Override - public LIRGenerator newLIRGenerator(CallingConvention cc, LIRGenerationResult lirGenRes) { + public LIRGeneratorTool newLIRGenerator(CallingConvention cc, LIRGenerationResult lirGenRes) { return new AMD64HotSpotLIRGenerator(getProviders(), getRuntime().getConfig(), cc, lirGenRes); } @@ -82,12 +82,12 @@ } @Override - public NodeLIRBuilder newNodeLIRGenerator(StructuredGraph graph, LIRGenerator lirGen) { + public NodeLIRBuilderTool newNodeLIRBuilder(StructuredGraph graph, LIRGeneratorTool lirGen) { return new AMD64HotSpotNodeLIRBuilder(graph, lirGen); } @Override - public BytecodeLIRBuilder newBytecodeLIRBuilder(LIRGenerator gen, BytecodeParserTool parser) { + public BytecodeLIRBuilder newBytecodeLIRBuilder(LIRGeneratorTool gen, BytecodeParserTool parser) { return new AMD64HotSpotBytecodeLIRBuilder(gen, parser); } @@ -225,7 +225,7 @@ Assembler masm = createAssembler(frameMap); HotSpotFrameContext frameContext = new HotSpotFrameContext(stub != null, omitFrame); CompilationResultBuilder crb = factory.createBuilder(getCodeCache(), getForeignCalls(), frameMap, masm, frameContext, compilationResult); - crb.setFrameSize(frameMap.frameSize()); + crb.setTotalFrameSize(frameMap.totalFrameSize()); StackSlot deoptimizationRescueSlot = gen.getDeoptimizationRescueSlot(); if (deoptimizationRescueSlot != null && stub == null) { crb.compilationResult.setCustomStackAreaOffset(frameMap.offsetForStackSlot(deoptimizationRescueSlot)); @@ -264,7 +264,7 @@ */ public void emitCodePrefix(ResolvedJavaMethod installedCodeOwner, CompilationResultBuilder crb, AMD64MacroAssembler asm, RegisterConfig regConfig, HotSpotVMConfig config, Label verifiedEntry) { HotSpotProviders providers = getProviders(); - if (installedCodeOwner != null && !isStatic(installedCodeOwner.getModifiers())) { + if (installedCodeOwner != null && !installedCodeOwner.isStatic()) { MarkId.recordMark(crb, MarkId.UNVERIFIED_ENTRY); CallingConvention cc = regConfig.getCallingConvention(JavaCallee, null, new JavaType[]{providers.getMetaAccess().lookupJavaType(Object.class)}, getTarget(), false); Register inlineCacheKlass = rax; // see definition of IC_Klass in diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotBytecodeLIRBuilder.java --- a/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotBytecodeLIRBuilder.java Fri Apr 25 16:21:07 2014 +0200 +++ b/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotBytecodeLIRBuilder.java Mon Apr 28 11:18:15 2014 +0200 @@ -24,17 +24,16 @@ import static com.oracle.graal.amd64.AMD64.*; -import java.lang.reflect.*; - import com.oracle.graal.api.code.*; import com.oracle.graal.api.meta.*; import com.oracle.graal.compiler.gen.*; import com.oracle.graal.hotspot.amd64.AMD64HotSpotLIRGenerator.SaveRbp; import com.oracle.graal.lir.StandardOp.NoOp; +import com.oracle.graal.lir.gen.*; public class AMD64HotSpotBytecodeLIRBuilder extends BytecodeLIRBuilder { - public AMD64HotSpotBytecodeLIRBuilder(LIRGenerator gen, BytecodeParserTool parser) { + public AMD64HotSpotBytecodeLIRBuilder(LIRGeneratorTool gen, BytecodeParserTool parser) { super(gen, parser); } @@ -72,7 +71,7 @@ gen.append(getSaveRbp().placeholder); Signature sig = method.getSignature(); - boolean isStatic = Modifier.isStatic(method.getModifiers()); + boolean isStatic = method.isStatic(); for (int i = 0; i < sig.getParameterCount(!isStatic); i++) { Value paramValue = params[i]; assert paramValue.getKind() == sig.getParameterKind(i).getStackKind(); diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotDeoptimizeCallerOp.java --- a/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotDeoptimizeCallerOp.java Fri Apr 25 16:21:07 2014 +0200 +++ b/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotDeoptimizeCallerOp.java Mon Apr 28 11:18:15 2014 +0200 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2014, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -26,6 +26,7 @@ import com.oracle.graal.asm.amd64.*; import com.oracle.graal.lir.*; +import com.oracle.graal.lir.StandardOp.*; import com.oracle.graal.lir.amd64.*; import com.oracle.graal.lir.asm.*; @@ -33,11 +34,11 @@ * Removes the current frame and tail calls the uncommon trap routine. */ @Opcode("DEOPT_CALLER") -final class AMD64HotSpotDeoptimizeCallerOp extends AMD64HotSpotEpilogueOp { +final class AMD64HotSpotDeoptimizeCallerOp extends AMD64HotSpotEpilogueOp implements BlockEndOp { @Override public void emitCode(CompilationResultBuilder crb, AMD64MacroAssembler masm) { leaveFrameAndRestoreRbp(crb, masm); - AMD64Call.directJmp(crb, masm, crb.foreignCalls.lookupForeignCall(UNCOMMON_TRAP)); + AMD64Call.directJmp(crb, masm, crb.foreignCalls.lookupForeignCall(UNCOMMON_TRAP_HANDLER)); } } diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotEnterUnpackFramesStackFrameOp.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotEnterUnpackFramesStackFrameOp.java Mon Apr 28 11:18:15 2014 +0200 @@ -0,0 +1,93 @@ +/* + * Copyright (c) 2013, 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.graal.hotspot.amd64; + +import static com.oracle.graal.amd64.AMD64.*; +import static com.oracle.graal.api.code.ValueUtil.*; +import static com.oracle.graal.lir.LIRInstruction.OperandFlag.*; + +import com.oracle.graal.api.code.*; +import com.oracle.graal.api.meta.*; +import com.oracle.graal.asm.amd64.*; +import com.oracle.graal.hotspot.stubs.*; +import com.oracle.graal.lir.*; +import com.oracle.graal.lir.amd64.*; +import com.oracle.graal.lir.asm.*; + +/** + * Emits code that enters a stack frame which is tailored to call the C++ method + * {@link DeoptimizationStub#UNPACK_FRAMES Deoptimization::unpack_frames}. + */ +@Opcode("ENTER_UNPACK_FRAMES_STACK_FRAME") +final class AMD64HotSpotEnterUnpackFramesStackFrameOp extends AMD64LIRInstruction { + + private final Register thread; + private final int threadLastJavaSpOffset; + private final int threadLastJavaPcOffset; + private final int threadLastJavaFpOffset; + @Alive(REG) AllocatableValue framePc; + @Alive(REG) AllocatableValue senderSp; + @Alive(REG) AllocatableValue senderFp; + + AMD64HotSpotEnterUnpackFramesStackFrameOp(Register thread, int threadLastJavaSpOffset, int threadLastJavaPcOffset, int threadLastJavaFpOffset, AllocatableValue framePc, AllocatableValue senderSp, + AllocatableValue senderFp) { + this.thread = thread; + this.threadLastJavaSpOffset = threadLastJavaSpOffset; + this.threadLastJavaPcOffset = threadLastJavaPcOffset; + this.threadLastJavaFpOffset = threadLastJavaFpOffset; + this.framePc = framePc; + this.senderSp = senderSp; + this.senderFp = senderFp; + } + + @Override + public void emitCode(CompilationResultBuilder crb, AMD64MacroAssembler masm) { + final int totalFrameSize = crb.frameMap.totalFrameSize(); + masm.push(asRegister(framePc)); + masm.push(asRegister(senderFp)); + masm.movq(rbp, rsp); + + /* + * Allocate a full sized frame. Since return address and base pointer are already in place + * (see above) we allocate two words less. + */ + masm.decrementq(rsp, totalFrameSize - 2 * crb.target.wordSize); + + // Set up last Java values. + masm.movq(new AMD64Address(thread, threadLastJavaSpOffset), rsp); + + /* + * Save the PC since it cannot easily be retrieved using the last Java SP after we aligned + * SP. Don't need the precise return PC here, just precise enough to point into this code + * blob. + */ + masm.leaq(rax, new AMD64Address(rip, 0)); + masm.movq(new AMD64Address(thread, threadLastJavaPcOffset), rax); + + // Use BP because the frames look interpreted now. + masm.movq(new AMD64Address(thread, threadLastJavaFpOffset), rbp); + + // Align the stack for the following unpackFrames call. + masm.andq(rsp, -(crb.target.stackAlignment)); + } +} diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotEpilogueOp.java --- a/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotEpilogueOp.java Fri Apr 25 16:21:07 2014 +0200 +++ b/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotEpilogueOp.java Mon Apr 28 11:18:15 2014 +0200 @@ -29,7 +29,6 @@ import com.oracle.graal.api.code.*; import com.oracle.graal.api.meta.*; import com.oracle.graal.asm.amd64.*; -import com.oracle.graal.lir.StandardOp.BlockEndOp; import com.oracle.graal.lir.*; import com.oracle.graal.lir.amd64.*; import com.oracle.graal.lir.asm.*; @@ -37,7 +36,7 @@ /** * Superclass for operations that use the value of RBP saved in a method's prologue. */ -abstract class AMD64HotSpotEpilogueOp extends AMD64LIRInstruction implements BlockEndOp { +abstract class AMD64HotSpotEpilogueOp extends AMD64LIRInstruction { /** * The type of location (i.e., stack or register) in which RBP is saved is not known until diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotForeignCallsProvider.java --- a/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotForeignCallsProvider.java Fri Apr 25 16:21:07 2014 +0200 +++ b/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotForeignCallsProvider.java Mon Apr 28 11:18:15 2014 +0200 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 2014, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -36,7 +36,7 @@ import com.oracle.graal.api.code.*; import com.oracle.graal.api.meta.*; -import com.oracle.graal.graph.*; +import com.oracle.graal.compiler.common.*; import com.oracle.graal.hotspot.*; import com.oracle.graal.hotspot.meta.*; @@ -51,7 +51,8 @@ @Override public void initialize(HotSpotProviders providers, HotSpotVMConfig config) { - Kind word = providers.getCodeCache().getTarget().wordKind; + TargetDescription target = providers.getCodeCache().getTarget(); + Kind word = target.wordKind; // The calling convention for the exception handler stub is (only?) defined in // TemplateInterpreterGenerator::generate_throw_exception() @@ -62,6 +63,8 @@ register(new HotSpotForeignCallLinkage(EXCEPTION_HANDLER, 0L, PRESERVES_REGISTERS, LEAF_NOFP, null, exceptionCc, NOT_REEXECUTABLE, ANY_LOCATION)); register(new HotSpotForeignCallLinkage(EXCEPTION_HANDLER_IN_CALLER, JUMP_ADDRESS, PRESERVES_REGISTERS, LEAF_NOFP, exceptionCc, null, NOT_REEXECUTABLE, ANY_LOCATION)); + link(new AMD64DeoptimizationStub(providers, target, registerStubCall(UNCOMMON_TRAP_HANDLER, REEXECUTABLE, LEAF, NO_LOCATIONS))); + // When the java.ext.dirs property is modified then the crypto classes might not be found. // If that's the case we ignore the ClassNotFoundException and continue since we cannot // replace a non-existing method anyway. diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotJumpToExceptionHandlerInCallerOp.java --- a/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotJumpToExceptionHandlerInCallerOp.java Fri Apr 25 16:21:07 2014 +0200 +++ b/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotJumpToExceptionHandlerInCallerOp.java Mon Apr 28 11:18:15 2014 +0200 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2014, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -31,6 +31,7 @@ import com.oracle.graal.asm.amd64.*; import com.oracle.graal.asm.amd64.AMD64Assembler.ConditionFlag; import com.oracle.graal.lir.*; +import com.oracle.graal.lir.StandardOp.*; import com.oracle.graal.lir.asm.*; /** @@ -38,7 +39,7 @@ * and jumps to the handler. */ @Opcode("JUMP_TO_EXCEPTION_HANDLER_IN_CALLER") -final class AMD64HotSpotJumpToExceptionHandlerInCallerOp extends AMD64HotSpotEpilogueOp { +final class AMD64HotSpotJumpToExceptionHandlerInCallerOp extends AMD64HotSpotEpilogueOp implements BlockEndOp { @Use(REG) AllocatableValue handlerInCallerPc; @Use(REG) AllocatableValue exception; diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotLIRGenerationResult.java --- a/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotLIRGenerationResult.java Fri Apr 25 16:21:07 2014 +0200 +++ b/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotLIRGenerationResult.java Mon Apr 28 11:18:15 2014 +0200 @@ -25,10 +25,10 @@ import java.util.*; import com.oracle.graal.api.code.*; -import com.oracle.graal.compiler.gen.*; import com.oracle.graal.hotspot.stubs.*; import com.oracle.graal.lir.*; import com.oracle.graal.lir.StandardOp.SaveRegistersOp; +import com.oracle.graal.lir.gen.*; public class AMD64HotSpotLIRGenerationResult extends LIRGenerationResultBase { diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotLIRGenerator.java --- a/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotLIRGenerator.java Fri Apr 25 16:21:07 2014 +0200 +++ b/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotLIRGenerator.java Mon Apr 28 11:18:15 2014 +0200 @@ -25,26 +25,29 @@ import static com.oracle.graal.amd64.AMD64.*; import static com.oracle.graal.api.code.ValueUtil.*; import static com.oracle.graal.hotspot.HotSpotGraalRuntime.*; +import static com.oracle.graal.hotspot.nodes.UncommonTrapCallNode.*; +import static com.oracle.graal.lir.LIRInstruction.OperandFlag.*; import java.util.*; import com.oracle.graal.amd64.*; import com.oracle.graal.api.code.*; import com.oracle.graal.api.meta.*; +import com.oracle.graal.asm.amd64.*; import com.oracle.graal.compiler.amd64.*; -import com.oracle.graal.compiler.gen.*; -import com.oracle.graal.graph.*; +import com.oracle.graal.compiler.common.*; +import com.oracle.graal.compiler.common.calc.*; import com.oracle.graal.hotspot.*; import com.oracle.graal.hotspot.HotSpotVMConfig.CompressEncoding; -import com.oracle.graal.hotspot.amd64.AMD64HotSpotMove.LoadCompressedPointer; -import com.oracle.graal.hotspot.amd64.AMD64HotSpotMove.StoreCompressedConstantOp; -import com.oracle.graal.hotspot.amd64.AMD64HotSpotMove.StoreCompressedPointer; +import com.oracle.graal.hotspot.data.*; import com.oracle.graal.hotspot.meta.*; import com.oracle.graal.hotspot.nodes.type.*; import com.oracle.graal.hotspot.stubs.*; import com.oracle.graal.lir.*; import com.oracle.graal.lir.StandardOp.NoOp; +import com.oracle.graal.lir.StandardOp.SaveRegistersOp; import com.oracle.graal.lir.amd64.*; +import com.oracle.graal.lir.amd64.AMD64ControlFlow.BranchOp; import com.oracle.graal.lir.amd64.AMD64ControlFlow.CondMoveOp; import com.oracle.graal.lir.amd64.AMD64Move.CompareAndSwapOp; import com.oracle.graal.lir.amd64.AMD64Move.LeaDataOp; @@ -53,9 +56,8 @@ import com.oracle.graal.lir.amd64.AMD64Move.MoveToRegOp; import com.oracle.graal.lir.amd64.AMD64Move.StoreConstantOp; import com.oracle.graal.lir.amd64.AMD64Move.StoreOp; -import com.oracle.graal.nodes.*; -import com.oracle.graal.nodes.calc.*; -import com.oracle.graal.nodes.extended.*; +import com.oracle.graal.lir.asm.*; +import com.oracle.graal.lir.gen.*; /** * LIR generator specialized for AMD64 HotSpot. @@ -63,6 +65,7 @@ public class AMD64HotSpotLIRGenerator extends AMD64LIRGenerator implements HotSpotLIRGenerator { final HotSpotVMConfig config; + private HotSpotLockStack lockStack; protected AMD64HotSpotLIRGenerator(HotSpotProviders providers, HotSpotVMConfig config, CallingConvention cc, LIRGenerationResult lirGenRes) { super(providers, cc, lirGenRes); @@ -129,7 +132,17 @@ @Override public StackSlot getLockSlot(int lockDepth) { - return ((HotSpotDebugInfoBuilder) getDebugInfoBuilder()).lockStack().makeLockSlot(lockDepth); + return getLockStack().makeLockSlot(lockDepth); + } + + private HotSpotLockStack getLockStack() { + assert lockStack != null; + return lockStack; + } + + protected void setLockStack(HotSpotLockStack lockStack) { + assert this.lockStack == null; + this.lockStack = lockStack; } private Register findPollOnReturnScratchRegister() { @@ -158,7 +171,7 @@ } @Override - protected boolean needOnlyOopMaps() { + public boolean needOnlyOopMaps() { // Stubs only need oop maps return ((AMD64HotSpotLIRGenerationResult) getResult()).getStub() != null; } @@ -176,12 +189,65 @@ super.emitForeignCall(linkage, result, arguments, temps, info); } - protected AMD64SaveRegistersOp emitSaveRegisters(Register[] savedRegisters, StackSlot[] savedRegisterLocations) { - AMD64SaveRegistersOp save = new AMD64SaveRegistersOp(savedRegisters, savedRegisterLocations, true); + public void emitLeaveCurrentStackFrame() { + append(new AMD64HotSpotLeaveCurrentStackFrameOp()); + } + + public void emitLeaveDeoptimizedStackFrame(Value frameSize, Value initialInfo) { + Variable frameSizeVariable = load(frameSize); + Variable initialInfoVariable = load(initialInfo); + append(new AMD64HotSpotLeaveDeoptimizedStackFrameOp(frameSizeVariable, initialInfoVariable)); + } + + public void emitEnterUnpackFramesStackFrame(Value framePc, Value senderSp, Value senderFp) { + Register thread = getProviders().getRegisters().getThreadRegister(); + Variable framePcVariable = load(framePc); + Variable senderSpVariable = load(senderSp); + Variable senderFpVariable = load(senderFp); + append(new AMD64HotSpotEnterUnpackFramesStackFrameOp(thread, config.threadLastJavaSpOffset(), config.threadLastJavaPcOffset(), config.threadLastJavaFpOffset(), framePcVariable, + senderSpVariable, senderFpVariable)); + } + + public void emitLeaveUnpackFramesStackFrame() { + Register thread = getProviders().getRegisters().getThreadRegister(); + append(new AMD64HotSpotLeaveUnpackFramesStackFrameOp(thread, config.threadLastJavaSpOffset(), config.threadLastJavaPcOffset(), config.threadLastJavaFpOffset())); + } + + /** + * @param savedRegisters the registers saved by this operation which may be subject to pruning + * @param savedRegisterLocations the slots to which the registers are saved + * @param supportsRemove determines if registers can be pruned + */ + protected AMD64SaveRegistersOp emitSaveRegisters(Register[] savedRegisters, StackSlot[] savedRegisterLocations, boolean supportsRemove) { + AMD64SaveRegistersOp save = new AMD64SaveRegistersOp(savedRegisters, savedRegisterLocations, supportsRemove); append(save); return save; } + /** + * Adds a node to the graph that saves all allocatable registers to the stack. + * + * @param supportsRemove determines if registers can be pruned + * @return the register save node + */ + private AMD64SaveRegistersOp emitSaveAllRegisters(Register[] savedRegisters, boolean supportsRemove) { + StackSlot[] savedRegisterLocations = new StackSlot[savedRegisters.length]; + for (int i = 0; i < savedRegisters.length; i++) { + PlatformKind kind = target().arch.getLargestStorableKind(savedRegisters[i].getRegisterCategory()); + assert kind != Kind.Illegal; + StackSlot spillSlot = getResult().getFrameMap().allocateSpillSlot(kind); + savedRegisterLocations[i] = spillSlot; + } + return emitSaveRegisters(savedRegisters, savedRegisterLocations, supportsRemove); + } + + @Override + public SaveRegistersOp emitSaveAllRegisters() { + // We are saving all registers. + // TODO Save upper half of YMM registers. + return emitSaveAllRegisters(cpuxmmRegisters, false); + } + protected void emitRestoreRegisters(AMD64SaveRegistersOp save) { append(new AMD64RestoreRegistersOp(save.getSlots().clone(), save)); } @@ -191,32 +257,25 @@ } @Override - public Variable emitForeignCall(ForeignCallLinkage linkage, DeoptimizingNode info, Value... args) { + public Variable emitForeignCall(ForeignCallLinkage linkage, LIRFrameState state, Value... args) { HotSpotForeignCallLinkage hotspotLinkage = (HotSpotForeignCallLinkage) linkage; boolean destroysRegisters = hotspotLinkage.destroysRegisters(); AMD64SaveRegistersOp save = null; - StackSlot[] savedRegisterLocations = null; if (destroysRegisters) { if (getStub() != null) { if (getStub().preservesRegisters()) { Register[] savedRegisters = getResult().getFrameMap().registerConfig.getAllocatableRegisters(); - savedRegisterLocations = new StackSlot[savedRegisters.length]; - for (int i = 0; i < savedRegisters.length; i++) { - PlatformKind kind = target().arch.getLargestStorableKind(savedRegisters[i].getRegisterCategory()); - assert kind != Kind.Illegal; - StackSlot spillSlot = getResult().getFrameMap().allocateSpillSlot(kind); - savedRegisterLocations[i] = spillSlot; - } - save = emitSaveRegisters(savedRegisters, savedRegisterLocations); + save = emitSaveAllRegisters(savedRegisters, true); } } } Variable result; - DeoptimizingNode deoptInfo = null; + // TODO (je) check if we can remove this + LIRFrameState deoptInfo = null; if (hotspotLinkage.canDeoptimize()) { - deoptInfo = info; + deoptInfo = state; assert deoptInfo != null || getStub() != null; assert hotspotLinkage.needsJavaFrameAnchor(); } @@ -227,15 +286,16 @@ result = super.emitForeignCall(hotspotLinkage, deoptInfo, args); append(new AMD64HotSpotCRuntimeCallEpilogueOp(config.threadLastJavaSpOffset(), config.threadLastJavaFpOffset(), thread)); } else { - result = super.emitForeignCall(hotspotLinkage, deoptInfo, args); + assert deoptInfo == null; + result = super.emitForeignCall(hotspotLinkage, null, args); } if (destroysRegisters) { if (getStub() != null) { if (getStub().preservesRegisters()) { - assert !((AMD64HotSpotLIRGenerationResult) getResult()).getCalleeSaveInfo().containsKey(currentRuntimeCallInfo); - ((AMD64HotSpotLIRGenerationResult) getResult()).getCalleeSaveInfo().put(currentRuntimeCallInfo, save); - + AMD64HotSpotLIRGenerationResult generationResult = (AMD64HotSpotLIRGenerationResult) getResult(); + assert !generationResult.getCalleeSaveInfo().containsKey(currentRuntimeCallInfo); + generationResult.getCalleeSaveInfo().put(currentRuntimeCallInfo, save); emitRestoreRegisters(save); } else { assert zapRegisters(); @@ -246,6 +306,21 @@ return result; } + public Value emitUncommonTrapCall(Value trapRequest, SaveRegistersOp saveRegisterOp) { + ForeignCallLinkage linkage = getForeignCalls().lookupForeignCall(UNCOMMON_TRAP); + + Register thread = getProviders().getRegisters().getThreadRegister(); + append(new AMD64HotSpotCRuntimeCallPrologueOp(config.threadLastJavaSpOffset(), thread)); + Variable result = super.emitForeignCall(linkage, null, thread.asValue(Kind.Long), trapRequest); + append(new AMD64HotSpotCRuntimeCallEpilogueOp(config.threadLastJavaSpOffset(), config.threadLastJavaFpOffset(), thread)); + + Map calleeSaveInfo = ((AMD64HotSpotLIRGenerationResult) getResult()).getCalleeSaveInfo(); + assert !calleeSaveInfo.containsKey(currentRuntimeCallInfo); + calleeSaveInfo.put(currentRuntimeCallInfo, saveRegisterOp); + + return result; + } + protected AMD64ZapRegistersOp emitZapRegisters(Register[] zappedRegisters, Constant[] zapValues) { AMD64ZapRegistersOp zap = new AMD64ZapRegistersOp(zappedRegisters, zapValues); append(zap); @@ -310,9 +385,9 @@ } @Override - public void emitDeoptimize(Value actionAndReason, Value speculation, DeoptimizingNode deopting) { + public void emitDeoptimize(Value actionAndReason, Value speculation, LIRFrameState state) { moveDeoptValuesToThread(actionAndReason, speculation); - append(new AMD64DeoptimizeOp(state(deopting))); + append(new AMD64DeoptimizeOp(state)); } @Override @@ -336,13 +411,6 @@ } /** - * Returns whether or not the input access should be (de)compressed. - */ - private boolean isCompressedOperation(PlatformKind kind, Access access) { - return access != null && access.isCompressible() && ((kind == Kind.Long && config.useCompressedClassPointers) || (kind == Kind.Object && config.useCompressedOops)); - } - - /** * @return a compressed version of the incoming constant */ protected static Constant compress(Constant c, CompressEncoding encoding) { @@ -374,86 +442,34 @@ } } + public void emitPushInterpreterFrame(Value frameSize, Value framePc, Value senderSp, Value initialInfo) { + Variable frameSizeVariable = load(frameSize); + Variable framePcVariable = load(framePc); + Variable senderSpVariable = load(senderSp); + Variable initialInfoVariable = load(initialInfo); + append(new AMD64HotSpotPushInterpreterFrameOp(frameSizeVariable, framePcVariable, senderSpVariable, initialInfoVariable)); + } + @Override - public Variable emitLoad(PlatformKind kind, Value address, Access access) { + public Variable emitLoad(PlatformKind kind, Value address, LIRFrameState state) { AMD64AddressValue loadAddress = asAddressValue(address); Variable result = newVariable(toStackKind(kind)); - LIRFrameState state = null; - if (access instanceof DeoptimizingNode) { - state = state((DeoptimizingNode) access); - } - /** - * Currently, the (de)compression of pointers applies conditionally to some objects (oops, - * kind==Object) and some addresses (klass pointers, kind==Long). Initially, the input - * operation is checked to discover if it has been tagged as a potential "compression" - * candidate. Consequently, depending on the appropriate kind, the specific (de)compression - * functions are being called. - */ - if (isCompressedOperation(kind, access)) { - if (kind == Kind.Object) { - append(new LoadCompressedPointer(Kind.Object, result, getProviders().getRegisters().getHeapBaseRegister().asValue(), loadAddress, state, config.getOopEncoding())); - } else if (kind == Kind.Long) { - Variable scratch = config.getKlassEncoding().base != 0 ? newVariable(Kind.Long) : null; - append(new LoadCompressedPointer(Kind.Long, result, scratch, loadAddress, state, config.getKlassEncoding())); - } else { - throw GraalInternalError.shouldNotReachHere("can't handle: " + access); - } - } else { - append(new LoadOp(getMemoryKind(kind), result, loadAddress, state)); - } + append(new LoadOp(getMemoryKind(kind), result, loadAddress, state)); return result; } @Override - public void emitStore(PlatformKind kind, Value address, Value inputVal, Access access) { + public void emitStore(PlatformKind kind, Value address, Value inputVal, LIRFrameState state) { AMD64AddressValue storeAddress = asAddressValue(address); - LIRFrameState state = null; - if (access instanceof DeoptimizingNode) { - state = state((DeoptimizingNode) access); - } - boolean isCompressed = isCompressedOperation(kind, access); if (isConstant(inputVal)) { Constant c = asConstant(inputVal); - if (canStoreConstant(c, isCompressed)) { - if (isCompressed) { - if (c.getKind() == Kind.Object) { - append(new StoreCompressedConstantOp(Kind.Object, storeAddress, c, state)); - } else if (c.getKind() == Kind.Long) { - // It's always a good idea to directly store compressed constants since they - // have to be materialized as 64 bits encoded otherwise. - Constant value = compress(c, config.getKlassEncoding()); - append(new StoreCompressedConstantOp(Kind.Long, storeAddress, value, state)); - } else { - throw GraalInternalError.shouldNotReachHere("can't handle: " + access); - } - return; - } else { - append(new StoreConstantOp(getMemoryKind(kind), storeAddress, c, state)); - return; - } + if (canStoreConstant(c, false)) { + append(new StoreConstantOp(getMemoryKind(kind), storeAddress, c, state)); + return; } } Variable input = load(inputVal); - if (isCompressed) { - if (kind == Kind.Object) { - if (input.getKind() == Kind.Object) { - Variable scratch = newVariable(Kind.Long); - Register heapBaseReg = getProviders().getRegisters().getHeapBaseRegister(); - append(new StoreCompressedPointer(Kind.Object, storeAddress, input, scratch, state, config.getOopEncoding(), heapBaseReg)); - } else { - // the input oop is already compressed - append(new StoreOp(input.getKind(), storeAddress, input, state)); - } - } else if (kind == Kind.Long) { - Variable scratch = newVariable(Kind.Long); - Register heapBaseReg = getProviders().getRegisters().getHeapBaseRegister(); - append(new StoreCompressedPointer(Kind.Long, storeAddress, input, scratch, state, config.getKlassEncoding(), heapBaseReg)); - } else { - append(new StoreOp(getMemoryKind(kind), storeAddress, input, state)); - } - } else { - append(new StoreOp(getMemoryKind(kind), storeAddress, input, state)); - } + append(new StoreOp(getMemoryKind(kind), storeAddress, input, state)); } @Override @@ -507,7 +523,6 @@ } } - @Override public Value emitCompareAndSwap(Value address, Value expectedValue, Value newValue, Value trueValue, Value falseValue) { PlatformKind kind = newValue.getPlatformKind(); assert kind == expectedValue.getPlatformKind(); @@ -523,4 +538,73 @@ append(new CondMoveOp(result, Condition.EQ, asAllocatable(trueValue), falseValue)); return result; } + + public Value emitAtomicReadAndAdd(Value address, Value delta) { + PlatformKind kind = delta.getPlatformKind(); + Kind memKind = getMemoryKind(kind); + Variable result = newVariable(kind); + AMD64AddressValue addressValue = asAddressValue(address); + append(new AMD64Move.AtomicReadAndAddOp(memKind, result, addressValue, asAllocatable(delta))); + return result; + } + + public Value emitAtomicReadAndWrite(Value address, Value newValue) { + PlatformKind kind = newValue.getPlatformKind(); + Kind memKind = getMemoryKind(kind); + Variable result = newVariable(kind); + AMD64AddressValue addressValue = asAddressValue(address); + append(new AMD64Move.AtomicReadAndWriteOp(memKind, result, addressValue, asAllocatable(newValue))); + return result; + } + + public static class CompareMemoryCompressedOp extends AMD64LIRInstruction { + @Alive({COMPOSITE}) protected AMD64AddressValue x; + @Use({CONST, REG}) protected Value y; + @State protected LIRFrameState state; + + public CompareMemoryCompressedOp(AMD64AddressValue x, Value y, LIRFrameState state) { + assert HotSpotGraalRuntime.runtime().getConfig().useCompressedOops; + this.x = x; + this.y = y; + this.state = state; + } + + @Override + public void emitCode(CompilationResultBuilder crb, AMD64MacroAssembler masm) { + if (state != null) { + crb.recordImplicitException(masm.position(), state); + } + if (y instanceof Constant) { + Constant constant = (Constant) y; + if (constant.isNull()) { + masm.cmpl(x.toAddress(), 0); + } else { + if (y.getKind() == Kind.Object) { + crb.recordInlineDataInCode(new OopData(0, HotSpotObjectConstant.asObject(constant), true)); + } else if (y.getKind() == Kind.Long) { + crb.recordInlineDataInCode(new MetaspaceData(0, constant.asLong(), HotSpotMetaspaceConstant.getMetaspaceObject(constant), true)); + } else { + throw GraalInternalError.shouldNotReachHere(); + } + masm.cmpl(x.toAddress(), 0xdeaddead); + } + } else { + masm.cmpl(asRegister(y), x.toAddress()); + } + } + } + + protected void emitCompareBranchMemoryCompressed(Value left, Value right, Condition cond, LabelRef trueLabel, LabelRef falseLabel, double trueLabelProbability, LIRFrameState state) { + boolean mirrored = false; + if (left instanceof AMD64AddressValue) { + append(new CompareMemoryCompressedOp((AMD64AddressValue) left, right, state)); + } else { + assert right instanceof AMD64AddressValue; + append(new CompareMemoryCompressedOp((AMD64AddressValue) right, left, state)); + mirrored = true; + } + + Condition finalCondition = mirrored ? cond.mirror() : cond; + append(new BranchOp(finalCondition, trueLabel, falseLabel, trueLabelProbability)); + } } diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotLeaveCurrentStackFrameOp.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotLeaveCurrentStackFrameOp.java Mon Apr 28 11:18:15 2014 +0200 @@ -0,0 +1,42 @@ +/* + * Copyright (c) 2013, 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.graal.hotspot.amd64; + +import static com.oracle.graal.amd64.AMD64.*; + +import com.oracle.graal.asm.amd64.*; +import com.oracle.graal.lir.*; +import com.oracle.graal.lir.asm.*; + +/** + * Pops the current frame off the stack including the return address. + */ +@Opcode("LEAVE_CURRENT_STACK_FRAME") +final class AMD64HotSpotLeaveCurrentStackFrameOp extends AMD64HotSpotEpilogueOp { + + @Override + public void emitCode(CompilationResultBuilder crb, AMD64MacroAssembler masm) { + leaveFrameAndRestoreRbp(crb, masm); + masm.addq(rsp, crb.target.arch.getReturnAddressSize()); + } +} diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotLeaveDeoptimizedStackFrameOp.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotLeaveDeoptimizedStackFrameOp.java Mon Apr 28 11:18:15 2014 +0200 @@ -0,0 +1,55 @@ +/* + * 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.amd64; + +import static com.oracle.graal.api.code.ValueUtil.*; +import static com.oracle.graal.amd64.AMD64.*; +import static com.oracle.graal.lir.LIRInstruction.OperandFlag.*; + +import com.oracle.graal.api.meta.*; +import com.oracle.graal.asm.amd64.*; +import com.oracle.graal.lir.*; +import com.oracle.graal.lir.asm.*; + +/** + * Pops the current frame off the stack including the return address. + */ +@Opcode("LEAVE_DEOPTIMIZED_STACK_FRAME") +final class AMD64HotSpotLeaveDeoptimizedStackFrameOp extends AMD64HotSpotEpilogueOp { + + @Use(REG) AllocatableValue frameSize; + @Use(REG) AllocatableValue framePointer; + + public AMD64HotSpotLeaveDeoptimizedStackFrameOp(AllocatableValue frameSize, AllocatableValue initialInfo) { + this.frameSize = frameSize; + this.framePointer = initialInfo; + } + + @Override + public void emitCode(CompilationResultBuilder crb, AMD64MacroAssembler masm) { + masm.addq(rsp, asRegister(frameSize)); + // Restore the frame pointer before stack bang because if a stack overflow is thrown it + // needs to be pushed (and preserved). + masm.movq(rbp, asRegister(framePointer)); + } +} diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotLeaveUnpackFramesStackFrameOp.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotLeaveUnpackFramesStackFrameOp.java Mon Apr 28 11:18:15 2014 +0200 @@ -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.amd64; + +import static com.oracle.graal.amd64.AMD64.*; + +import com.oracle.graal.api.code.*; +import com.oracle.graal.asm.amd64.*; +import com.oracle.graal.hotspot.stubs.*; +import com.oracle.graal.lir.*; +import com.oracle.graal.lir.amd64.*; +import com.oracle.graal.lir.asm.*; + +/** + * Emits code that leaves a stack frame which is tailored to call the C++ method + * {@link DeoptimizationStub#UNPACK_FRAMES Deoptimization::unpack_frames}. + */ +@Opcode("LEAVE_UNPACK_FRAMES_STACK_FRAME") +final class AMD64HotSpotLeaveUnpackFramesStackFrameOp extends AMD64LIRInstruction { + + private final Register thread; + private final int threadLastJavaSpOffset; + private final int threadLastJavaPcOffset; + private final int threadLastJavaFpOffset; + + AMD64HotSpotLeaveUnpackFramesStackFrameOp(Register thread, int threadLastJavaSpOffset, int threadLastJavaPcOffset, int threadLastJavaFpOffset) { + this.thread = thread; + this.threadLastJavaSpOffset = threadLastJavaSpOffset; + this.threadLastJavaPcOffset = threadLastJavaPcOffset; + this.threadLastJavaFpOffset = threadLastJavaFpOffset; + } + + @Override + public void emitCode(CompilationResultBuilder crb, AMD64MacroAssembler masm) { + // Restore stack pointer. + masm.movq(rsp, new AMD64Address(thread, threadLastJavaSpOffset)); + + // Clear last Java frame values. + masm.movslq(new AMD64Address(thread, threadLastJavaSpOffset), 0); + masm.movslq(new AMD64Address(thread, threadLastJavaPcOffset), 0); + masm.movslq(new AMD64Address(thread, threadLastJavaFpOffset), 0); + } +} diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotMemoryPeephole.java --- a/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotMemoryPeephole.java Fri Apr 25 16:21:07 2014 +0200 +++ b/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotMemoryPeephole.java Mon Apr 28 11:18:15 2014 +0200 @@ -23,21 +23,15 @@ package com.oracle.graal.hotspot.amd64; -import static com.oracle.graal.lir.LIRInstruction.OperandFlag.*; - import com.oracle.graal.api.meta.*; -import com.oracle.graal.asm.amd64.*; import com.oracle.graal.compiler.amd64.*; -import com.oracle.graal.graph.*; +import com.oracle.graal.compiler.common.calc.*; import com.oracle.graal.hotspot.*; -import com.oracle.graal.hotspot.data.*; -import com.oracle.graal.hotspot.meta.*; +import com.oracle.graal.hotspot.amd64.AMD64HotSpotLIRGenerator.CompareMemoryCompressedOp; +import com.oracle.graal.hotspot.nodes.type.*; import com.oracle.graal.lir.*; -import com.oracle.graal.lir.amd64.*; import com.oracle.graal.lir.amd64.AMD64ControlFlow.BranchOp; -import com.oracle.graal.lir.asm.*; import com.oracle.graal.nodes.*; -import com.oracle.graal.nodes.calc.*; import com.oracle.graal.nodes.extended.*; /** @@ -45,41 +39,18 @@ */ public class AMD64HotSpotMemoryPeephole extends AMD64MemoryPeephole { - public static class CompareMemoryCompressedOp extends AMD64LIRInstruction { - @Alive({COMPOSITE}) protected AMD64AddressValue x; - @Use({CONST}) protected Value y; - @State protected LIRFrameState state; - - public CompareMemoryCompressedOp(AMD64AddressValue x, Constant y, LIRFrameState state) { - assert HotSpotGraalRuntime.runtime().getConfig().useCompressedOops; - this.x = x; - this.y = y; - this.state = state; - } - - @Override - public void emitCode(CompilationResultBuilder crb, AMD64MacroAssembler masm) { - Constant constant = (Constant) y; - if (constant.isNull()) { - masm.cmpl(x.toAddress(), 0); - } else { - if (y.getKind() == Kind.Object) { - crb.recordInlineDataInCode(new OopData(0, HotSpotObjectConstant.asObject(constant), true)); - } else if (y.getKind() == Kind.Long) { - crb.recordInlineDataInCode(new MetaspaceData(0, constant.asLong(), HotSpotMetaspaceConstant.getMetaspaceObject(constant), true)); - } else { - throw GraalInternalError.shouldNotReachHere(); - } - if (state != null) { - crb.recordImplicitException(masm.position(), state); - } - masm.cmpl(x.toAddress(), 0xdeaddead); - } - } + AMD64HotSpotMemoryPeephole(AMD64NodeLIRBuilder gen) { + super(gen); } - AMD64HotSpotMemoryPeephole(AMD64NodeLIRBuilder gen) { - super(gen); + @Override + protected Kind getMemoryKind(Access access) { + PlatformKind kind = gen.getLIRGeneratorTool().getPlatformKind(access.asNode().stamp()); + if (kind == NarrowOopStamp.NarrowOop) { + return Kind.Int; + } else { + return (Kind) kind; + } } @Override @@ -87,7 +58,7 @@ double trueLabelProbability) { if (HotSpotGraalRuntime.runtime().getConfig().useCompressedOops) { ValueNode other = selectOtherInput(left, right, access); - Kind kind = access.accessLocation().getValueKind(); + Kind kind = getMemoryKind(access); if (other.isConstant() && kind == Kind.Object && access.isCompressible()) { ensureEvaluated(other); diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotMove.java --- a/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotMove.java Fri Apr 25 16:21:07 2014 +0200 +++ b/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotMove.java Mon Apr 28 11:18:15 2014 +0200 @@ -31,7 +31,7 @@ import com.oracle.graal.asm.*; import com.oracle.graal.asm.amd64.*; import com.oracle.graal.asm.amd64.AMD64Assembler.ConditionFlag; -import com.oracle.graal.graph.*; +import com.oracle.graal.compiler.common.*; import com.oracle.graal.hotspot.HotSpotVMConfig.CompressEncoding; import com.oracle.graal.hotspot.data.*; import com.oracle.graal.hotspot.meta.*; diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotNodeLIRBuilder.java --- a/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotNodeLIRBuilder.java Fri Apr 25 16:21:07 2014 +0200 +++ b/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotNodeLIRBuilder.java Mon Apr 28 11:18:15 2014 +0200 @@ -26,15 +26,15 @@ import static com.oracle.graal.api.code.ValueUtil.*; import static com.oracle.graal.hotspot.HotSpotBackend.*; -import java.lang.reflect.*; - import com.oracle.graal.amd64.*; import com.oracle.graal.api.code.*; import com.oracle.graal.api.meta.*; import com.oracle.graal.asm.*; import com.oracle.graal.asm.amd64.AMD64Address.Scale; import com.oracle.graal.compiler.amd64.*; +import com.oracle.graal.compiler.common.calc.*; import com.oracle.graal.compiler.gen.*; +import com.oracle.graal.compiler.match.*; import com.oracle.graal.debug.*; import com.oracle.graal.graph.*; import com.oracle.graal.hotspot.*; @@ -45,17 +45,55 @@ import com.oracle.graal.lir.StandardOp.NoOp; import com.oracle.graal.lir.amd64.*; import com.oracle.graal.lir.amd64.AMD64Move.CompareAndSwapOp; +import com.oracle.graal.lir.gen.*; import com.oracle.graal.nodes.*; +import com.oracle.graal.nodes.calc.*; +import com.oracle.graal.nodes.extended.*; import com.oracle.graal.nodes.java.MethodCallTargetNode.InvokeKind; /** * LIR generator specialized for AMD64 HotSpot. */ +@MatchableNodeImport({"com.oracle.graal.hotspot.nodes.HotSpotMatchableNodes"}) public class AMD64HotSpotNodeLIRBuilder extends AMD64NodeLIRBuilder implements HotSpotNodeLIRBuilder { - public AMD64HotSpotNodeLIRBuilder(StructuredGraph graph, LIRGenerator gen) { + private static ValueNode filterCompression(ValueNode node) { + ValueNode result = node; + while (result instanceof CompressionNode) { + result = ((CompressionNode) result).getInput(); + } + return result; + } + + private void emitCompareCompressedMemory(IfNode ifNode, ValueNode value, Access access, CompareNode compare) { + Condition cond = compare.condition(); + LabelRef trueLabel = getLIRBlock(ifNode.trueSuccessor()); + LabelRef falseLabel = getLIRBlock(ifNode.falseSuccessor()); + double trueLabelProbability = ifNode.probability(ifNode.trueSuccessor()); + Value left; + Value right; + if (access == filterCompression(compare.x())) { + if (value.isConstant()) { + left = value.asConstant(); + } else { + left = gen.loadNonConst(operand(value)); + } + right = makeAddress(access); + } else { + assert access == filterCompression(compare.y()); + left = makeAddress(access); + right = gen.loadNonConst(operand(value)); + cond = cond.mirror(); + } + getGen().emitCompareBranchMemoryCompressed(left, right, cond, trueLabel, falseLabel, trueLabelProbability, getState(access)); + } + + public AMD64HotSpotNodeLIRBuilder(StructuredGraph graph, LIRGeneratorTool gen) { super(graph, gen); memoryPeephole = new AMD64HotSpotMemoryPeephole(this); + assert gen instanceof AMD64HotSpotLIRGenerator; + assert getDebugInfoBuilder() instanceof HotSpotDebugInfoBuilder; + ((AMD64HotSpotLIRGenerator) gen).setLockStack(((HotSpotDebugInfoBuilder) getDebugInfoBuilder()).lockStack()); } private AMD64HotSpotLIRGenerator getGen() { @@ -107,7 +145,7 @@ @Override public void visitSafepointNode(SafepointNode i) { - LIRFrameState info = gen.state(i); + LIRFrameState info = state(i); append(new AMD64HotSpotSafepointOp(info, getGen().config, this)); } @@ -119,7 +157,7 @@ } else { assert invokeKind == InvokeKind.Static || invokeKind == InvokeKind.Special; HotSpotResolvedJavaMethod resolvedMethod = (HotSpotResolvedJavaMethod) callTarget.target(); - assert !Modifier.isAbstract(resolvedMethod.getModifiers()) : "Cannot make direct call to abstract method."; + assert !resolvedMethod.isAbstract() : "Cannot make direct call to abstract method."; append(new AMD64HotspotDirectStaticCallOp(callTarget.target(), result, parameters, temps, callState, invokeKind)); } } @@ -160,7 +198,7 @@ @Override public void visitInfopointNode(InfopointNode i) { - if (i.getState() != null && i.getState().bci == FrameState.AFTER_BCI) { + if (i.getState() != null && i.getState().bci == BytecodeFrame.AFTER_BCI) { Debug.log("Ignoring InfopointNode for AFTER_BCI"); } else { super.visitInfopointNode(i); @@ -199,4 +237,40 @@ gen.emitMove(result, raxLocal); setResult(x, result); } + + /** + * Helper class to convert the NodeLIRBuilder into the current subclass. + */ + static abstract class AMD64HotSpotMatchGenerator implements MatchGenerator { + public AMD64HotSpotMatchGenerator() { + } + + public ComplexMatchResult match(NodeLIRBuilder gen) { + return match((AMD64HotSpotNodeLIRBuilder) gen); + } + + abstract public ComplexMatchResult match(AMD64HotSpotNodeLIRBuilder gen); + } + + @MatchRule("(If (ObjectEquals=compare Constant=value (Compression Read=access)))") + @MatchRule("(If (ObjectEquals=compare Constant=value (Compression FloatingRead=access)))") + @MatchRule("(If (ObjectEquals=compare (Compression value) (Compression Read=access)))") + @MatchRule("(If (ObjectEquals=compare (Compression value) (Compression FloatingRead=access)))") + public static class IfCompareMemory extends AMD64HotSpotMatchGenerator { + IfNode root; + Access access; + ValueNode value; + CompareNode compare; + + @Override + public ComplexMatchResult match(AMD64HotSpotNodeLIRBuilder gen) { + if (HotSpotGraalRuntime.runtime().getConfig().useCompressedOops) { + return builder -> { + gen.emitCompareCompressedMemory(root, value, access, compare); + return null; + }; + } + return null; + } + } } diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotPushInterpreterFrameOp.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotPushInterpreterFrameOp.java Mon Apr 28 11:18:15 2014 +0200 @@ -0,0 +1,81 @@ +/* + * 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.amd64; + +import static com.oracle.graal.amd64.AMD64.*; +import static com.oracle.graal.api.code.ValueUtil.*; +import static com.oracle.graal.lir.LIRInstruction.OperandFlag.*; + +import com.oracle.graal.api.code.*; +import com.oracle.graal.api.meta.*; +import com.oracle.graal.asm.amd64.*; +import com.oracle.graal.hotspot.*; +import com.oracle.graal.lir.*; +import com.oracle.graal.lir.amd64.*; +import com.oracle.graal.lir.asm.*; + +/** + * Pushes an interpreter frame to the stack. + */ +@Opcode("PUSH_INTERPRETER_FRAME") +final class AMD64HotSpotPushInterpreterFrameOp extends AMD64LIRInstruction { + + @Alive(REG) AllocatableValue frameSize; + @Alive(REG) AllocatableValue framePc; + @Alive(REG) AllocatableValue senderSp; + @Alive(REG) AllocatableValue initialInfo; + + AMD64HotSpotPushInterpreterFrameOp(AllocatableValue frameSize, AllocatableValue framePc, AllocatableValue senderSp, AllocatableValue initialInfo) { + this.frameSize = frameSize; + this.framePc = framePc; + this.senderSp = senderSp; + this.initialInfo = initialInfo; + } + + @Override + public void emitCode(CompilationResultBuilder crb, AMD64MacroAssembler masm) { + final Register frameSizeRegister = asRegister(frameSize); + final Register framePcRegister = asRegister(framePc); + final Register senderSpRegister = asRegister(senderSp); + final Register initialInfoRegister = asRegister(initialInfo); + final HotSpotVMConfig config = HotSpotGraalRuntime.runtime().getConfig(); + final int wordSize = HotSpotGraalRuntime.runtime().getTarget().wordSize; + + // We'll push PC and BP by hand. + masm.subq(frameSizeRegister, 2 * wordSize); + + // Push return address. + masm.push(framePcRegister); + + // Prolog + masm.push(initialInfoRegister); + masm.movq(initialInfoRegister, rsp); + masm.subq(rsp, frameSizeRegister); + + // This value is corrected by layout_activation_impl. + masm.movptr(new AMD64Address(initialInfoRegister, config.frameInterpreterFrameLastSpOffset * wordSize), 0); + + // Make the frame walkable. + masm.movq(new AMD64Address(initialInfoRegister, config.frameInterpreterFrameSenderSpOffset * wordSize), senderSpRegister); + } +} diff -r 3dde8d8c95b8 -r 40d0022115ee 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 Fri Apr 25 16:21:07 2014 +0200 +++ b/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotRegisterConfig.java Mon Apr 28 11:18:15 2014 +0200 @@ -23,7 +23,7 @@ package com.oracle.graal.hotspot.amd64; import static com.oracle.graal.amd64.AMD64.*; -import static com.oracle.graal.phases.GraalOptions.*; +import static com.oracle.graal.compiler.common.GraalOptions.*; import java.util.*; @@ -31,10 +31,9 @@ import com.oracle.graal.api.code.*; import com.oracle.graal.api.code.CallingConvention.Type; import com.oracle.graal.api.meta.*; -import com.oracle.graal.graph.*; +import com.oracle.graal.compiler.common.*; import com.oracle.graal.hotspot.*; import com.oracle.graal.hotspot.nodes.type.*; -import com.oracle.graal.phases.*; public class AMD64HotSpotRegisterConfig implements RegisterConfig { diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotReturnOp.java --- a/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotReturnOp.java Fri Apr 25 16:21:07 2014 +0200 +++ b/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotReturnOp.java Mon Apr 28 11:18:15 2014 +0200 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2014, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -29,13 +29,14 @@ import com.oracle.graal.api.meta.*; import com.oracle.graal.asm.amd64.*; import com.oracle.graal.lir.*; +import com.oracle.graal.lir.StandardOp.*; import com.oracle.graal.lir.asm.*; /** * Returns from a function. */ @Opcode("RETURN") -final class AMD64HotSpotReturnOp extends AMD64HotSpotEpilogueOp { +final class AMD64HotSpotReturnOp extends AMD64HotSpotEpilogueOp implements BlockEndOp { @Use({REG, ILLEGAL}) protected Value value; private final boolean isStub; diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotSafepointOp.java --- a/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotSafepointOp.java Fri Apr 25 16:21:07 2014 +0200 +++ b/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotSafepointOp.java Mon Apr 28 11:18:15 2014 +0200 @@ -24,7 +24,7 @@ import static com.oracle.graal.amd64.AMD64.*; import static com.oracle.graal.asm.NumUtil.*; -import static com.oracle.graal.phases.GraalOptions.*; +import static com.oracle.graal.compiler.common.GraalOptions.*; import com.oracle.graal.api.code.*; import com.oracle.graal.api.meta.*; diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotUnwindOp.java --- a/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotUnwindOp.java Fri Apr 25 16:21:07 2014 +0200 +++ b/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotUnwindOp.java Mon Apr 28 11:18:15 2014 +0200 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2014, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -31,6 +31,7 @@ import com.oracle.graal.asm.amd64.*; import com.oracle.graal.hotspot.stubs.*; import com.oracle.graal.lir.*; +import com.oracle.graal.lir.StandardOp.*; import com.oracle.graal.lir.amd64.*; import com.oracle.graal.lir.asm.*; @@ -38,7 +39,7 @@ * Removes the current frame and jumps to the {@link UnwindExceptionToCallerStub}. */ @Opcode("UNWIND") -final class AMD64HotSpotUnwindOp extends AMD64HotSpotEpilogueOp { +final class AMD64HotSpotUnwindOp extends AMD64HotSpotEpilogueOp implements BlockEndOp { @Use({REG}) protected RegisterValue exception; diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotspotDirectStaticCallOp.java --- a/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotspotDirectStaticCallOp.java Fri Apr 25 16:21:07 2014 +0200 +++ b/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotspotDirectStaticCallOp.java Mon Apr 28 11:18:15 2014 +0200 @@ -31,8 +31,8 @@ import com.oracle.graal.nodes.java.MethodCallTargetNode.InvokeKind; /** - * A direct call that complies with the conventions for such calls in HotSpot. In particular, for - * calls using an inline cache, a MOVE instruction is emitted just prior to the aligned direct call. + * A direct call that complies with the conventions for such calls in HotSpot. It doesn't use an + * inline cache so it's just a patchable call site. */ @Opcode("CALL_DIRECT") final class AMD64HotspotDirectStaticCallOp extends DirectCallOp { diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64PrefetchOp.java --- a/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64PrefetchOp.java Fri Apr 25 16:21:07 2014 +0200 +++ b/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64PrefetchOp.java Mon Apr 28 11:18:15 2014 +0200 @@ -26,7 +26,7 @@ import static com.oracle.graal.lir.LIRInstruction.OperandFlag.*; import com.oracle.graal.asm.amd64.*; -import com.oracle.graal.graph.*; +import com.oracle.graal.compiler.common.*; import com.oracle.graal.lir.amd64.*; import com.oracle.graal.lir.asm.*; diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64RawNativeCallNode.java --- a/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64RawNativeCallNode.java Fri Apr 25 16:21:07 2014 +0200 +++ b/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64RawNativeCallNode.java Mon Apr 28 11:18:15 2014 +0200 @@ -26,13 +26,12 @@ import com.oracle.graal.api.code.CallingConvention.Type; import com.oracle.graal.api.meta.*; import com.oracle.graal.compiler.amd64.*; -import com.oracle.graal.compiler.gen.*; -import com.oracle.graal.compiler.target.*; +import com.oracle.graal.compiler.common.type.*; import com.oracle.graal.graph.*; import com.oracle.graal.nodes.*; -import com.oracle.graal.nodes.type.*; +import com.oracle.graal.nodes.spi.*; -public class AMD64RawNativeCallNode extends FixedWithNextNode implements LIRGenLowerable { +public class AMD64RawNativeCallNode extends FixedWithNextNode implements LIRLowerable { private final Constant functionPointer; @Input private final NodeInputList args; @@ -44,7 +43,7 @@ } @Override - public void generate(NodeLIRBuilder generator) { + public void generate(NodeLIRBuilderTool generator) { AMD64NodeLIRBuilder gen = (AMD64NodeLIRBuilder) generator; Value[] parameter = new Value[args.count()]; JavaType[] parameterTypes = new JavaType[args.count()]; @@ -55,7 +54,7 @@ ResolvedJavaType returnType = stamp().javaType(gen.getLIRGeneratorTool().getMetaAccess()); CallingConvention cc = generator.getLIRGeneratorTool().getCodeCache().getRegisterConfig().getCallingConvention(Type.NativeCall, returnType, parameterTypes, generator.getLIRGeneratorTool().target(), false); - ((AMD64LIRGenerator) gen.getLIRGeneratorTool()).emitCCall(functionPointer.asLong(), cc, parameter, countFloatingTypeArguments(args)); + gen.getLIRGeneratorTool().emitCCall(functionPointer.asLong(), cc, parameter, countFloatingTypeArguments(args)); if (this.getKind() != Kind.Void) { generator.setResult(this, gen.getLIRGeneratorTool().emitMove(cc.getReturn())); } diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.hotspot.hsail/src/com/oracle/graal/hotspot/hsail/DonorThreadPool.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.hotspot.hsail/src/com/oracle/graal/hotspot/hsail/DonorThreadPool.java Mon Apr 28 11:18:15 2014 +0200 @@ -0,0 +1,74 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.graal.hotspot.hsail; + +import static com.oracle.graal.hotspot.hsail.HSAILHotSpotBackend.Options.*; + +import java.util.concurrent.*; + +import com.oracle.graal.hotspot.hsail.HSAILHotSpotBackend.Options; + +/** + * Thread pool for HSAIL allocation support. + */ +public class DonorThreadPool { + + private final Thread[] threads; + + void waitAt(CyclicBarrier barrier) { + try { + barrier.await(); + } catch (Exception e) { + e.printStackTrace(); + } + } + + /** + * Creates a pool of threads whose size is given by {@link Options#HsailDonorThreads}. + */ + DonorThreadPool() { + int size = HsailDonorThreads.getValue(); + this.threads = new Thread[size]; + CyclicBarrier barrier = new CyclicBarrier(size + 1); + + // fill in threads + for (int i = 0; i < size; i++) { + threads[i] = new Thread(new Runnable() { + @Override + public void run() { + while (true) { + waitAt(barrier); + } + } + }, "HsailDonorThread-" + i); + threads[i].setDaemon(true); + threads[i].start(); + } + // creating thread waits at barrier to make sure others have started + waitAt(barrier); + } + + public Thread[] getThreads() { + return threads; + } +} \ No newline at end of file diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.hotspot.hsail/src/com/oracle/graal/hotspot/hsail/HSAILHotSpotBackend.java --- a/graal/com.oracle.graal.hotspot.hsail/src/com/oracle/graal/hotspot/hsail/HSAILHotSpotBackend.java Fri Apr 25 16:21:07 2014 +0200 +++ b/graal/com.oracle.graal.hotspot.hsail/src/com/oracle/graal/hotspot/hsail/HSAILHotSpotBackend.java Mon Apr 28 11:18:15 2014 +0200 @@ -27,6 +27,8 @@ import static com.oracle.graal.api.code.ValueUtil.*; import static com.oracle.graal.api.meta.LocationIdentity.*; import static com.oracle.graal.compiler.GraalCompiler.*; +import static com.oracle.graal.hotspot.hsail.HSAILHotSpotBackend.Options.*; +import static com.oracle.graal.hotspot.hsail.replacements.HSAILNewObjectSnippets.Options.*; import java.lang.reflect.*; import java.util.*; @@ -44,11 +46,12 @@ import com.oracle.graal.api.meta.*; import com.oracle.graal.asm.*; import com.oracle.graal.asm.hsail.*; -import com.oracle.graal.compiler.gen.*; +import com.oracle.graal.compiler.common.*; +import com.oracle.graal.compiler.common.cfg.*; +import com.oracle.graal.compiler.common.type.*; import com.oracle.graal.debug.*; import com.oracle.graal.debug.Debug.Scope; import com.oracle.graal.gpu.*; -import com.oracle.graal.graph.*; import com.oracle.graal.hotspot.*; import com.oracle.graal.hotspot.bridge.CompilerToVM.CodeInstallResult; import com.oracle.graal.hotspot.meta.*; @@ -57,14 +60,17 @@ import com.oracle.graal.java.*; import com.oracle.graal.lir.*; import com.oracle.graal.lir.asm.*; +import com.oracle.graal.lir.gen.*; import com.oracle.graal.lir.hsail.*; -import com.oracle.graal.lir.hsail.HSAILControlFlow.DeoptimizeOp; +import com.oracle.graal.lir.hsail.HSAILControlFlow.DeoptimizingOp; +import com.oracle.graal.lir.hsail.HSAILMove.AtomicReadAndAddOp; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.StructuredGraph.GuardsStage; import com.oracle.graal.nodes.calc.*; import com.oracle.graal.nodes.extended.*; import com.oracle.graal.nodes.java.*; -import com.oracle.graal.nodes.type.*; +import com.oracle.graal.nodes.spi.*; +import com.oracle.graal.options.*; import com.oracle.graal.phases.*; import com.oracle.graal.phases.tiers.*; @@ -73,6 +79,14 @@ */ public class HSAILHotSpotBackend extends HotSpotBackend { + public static class Options { + + // @formatter:off + @Option(help = "Number of donor threads for HSAIL kernel dispatch") + static public final OptionValue HsailDonorThreads = new OptionValue<>(4); + // @formatter:on + } + private Map paramTypeMap = new HashMap<>(); private final boolean deviceInitialized; // TODO: get maximum Concurrency from okra @@ -103,18 +117,6 @@ private static native boolean initialize(); /** - * Control how many threads run on simulator (used only from junit tests). - */ - public void setSimulatorSingleThreaded() { - String simThrEnv = System.getenv("SIMTHREADS"); - if (simThrEnv == null || !simThrEnv.equals("1")) { - setSimulatorSingleThreaded0(); - } - } - - private static native void setSimulatorSingleThreaded0(); - - /** * Determines if the GPU device (or simulator) is available and initialized. */ public boolean isDeviceInitialized() { @@ -257,7 +259,7 @@ Debug.log("Param count: %d", parameterTypes.length); for (int i = 0; i < parameterTypes.length; i++) { ParameterNode parameter = hostGraph.getParameter(i); - Debug.log("Param [%d]=%d", i, parameter); + Debug.log("Param [%d]=%s", i, parameter); parameterTypes[i] = parameter.stamp().javaType(hostBackend.getProviders().getMetaAccess()); Debug.log(" %s", parameterTypes[i]); } @@ -293,16 +295,15 @@ assert hsailCode.getDataReferences().isEmpty(); // from host code - result.setFrameSize(hostCode.getFrameSize()); + result.setTotalFrameSize(hostCode.getTotalFrameSize()); result.setCustomStackAreaOffset(hostCode.getCustomStackAreaOffset()); result.setRegisterRestoreEpilogueOffset(hostCode.getRegisterRestoreEpilogueOffset()); result.setTargetCode(hostCode.getTargetCode(), hostCode.getTargetCodeSize()); for (CodeAnnotation annotation : hostCode.getAnnotations()) { result.addAnnotation(annotation); } - CompilationResult.Mark[] noMarks = {}; for (Mark mark : hostCode.getMarks()) { - result.recordMark(mark.pcOffset, mark.id, noMarks); + result.recordMark(mark.pcOffset, mark.id); } for (ExceptionHandler handler : hostCode.getExceptionHandlers()) { result.recordExceptionHandler(handler.pcOffset, handler.handlerPos); @@ -347,15 +348,23 @@ return result; } + private static final ThreadLocal donorThreadPool = new ThreadLocal() { + @Override + protected DonorThreadPool initialValue() { + return new DonorThreadPool(); + } + }; + public boolean executeKernel(HotSpotInstalledCode kernel, int jobSize, Object[] args) throws InvalidInstalledCodeException { if (!deviceInitialized) { throw new GraalInternalError("Cannot execute GPU kernel if device is not initialized"); } Object[] oopsSaveArea = new Object[maxDeoptIndex * 16]; - return executeKernel0(kernel, jobSize, args, oopsSaveArea); + return executeKernel0(kernel, jobSize, args, oopsSaveArea, donorThreadPool.get().getThreads(), HsailAllocBytesPerWorkitem.getValue()); } - private static native boolean executeKernel0(HotSpotInstalledCode kernel, int jobSize, Object[] args, Object[] oopsSave) throws InvalidInstalledCodeException; + private static native boolean executeKernel0(HotSpotInstalledCode kernel, int jobSize, Object[] args, Object[] oopsSave, Thread[] donorThreads, int allocBytesPerWorkitem) + throws InvalidInstalledCodeException; /** * Use the HSAIL register set when the compilation target is HSAIL. @@ -366,7 +375,7 @@ } @Override - public LIRGenerator newLIRGenerator(CallingConvention cc, LIRGenerationResult lirGenRes) { + public LIRGeneratorTool newLIRGenerator(CallingConvention cc, LIRGenerationResult lirGenRes) { return new HSAILHotSpotLIRGenerator(getProviders(), getRuntime().getConfig(), cc, lirGenRes); } @@ -376,7 +385,7 @@ } @Override - public NodeLIRBuilder newNodeLIRGenerator(StructuredGraph graph, LIRGenerator lirGen) { + public NodeLIRBuilderTool newNodeLIRBuilder(StructuredGraph graph, LIRGeneratorTool lirGen) { return new HSAILHotSpotNodeLIRBuilder(graph, lirGen); } @@ -423,15 +432,32 @@ // save lirGen for later use by setHostGraph CompilationResultBuilder crb = new HSAILCompilationResultBuilder(getCodeCache(), getForeignCalls(), frameMap, masm, frameContext, compilationResult, (HSAILHotSpotLIRGenerationResult) lirGenRes); - crb.setFrameSize(frameMap.frameSize()); + crb.setTotalFrameSize(frameMap.totalFrameSize()); return crb; } @Override public void emitCode(CompilationResultBuilder crb, LIR lir, ResolvedJavaMethod method) { assert method != null : lir + " is not associated with a method"; + Kind wordKind = getProviders().getCodeCache().getTarget().wordKind; - boolean useHSAILDeoptimization = getRuntime().getConfig().useHSAILDeoptimization; + HotSpotVMConfig config = getRuntime().getConfig(); + boolean useHSAILDeoptimization = config.useHSAILDeoptimization; + boolean useHSAILSafepoints = config.useHSAILSafepoints; + + // see what graph nodes we have to see if we are using the thread register + // if not, we don't have to emit the code that sets that up + // maybe there is a better way to do this? + boolean usesThreadRegister = false; + search: for (AbstractBlock b : lir.linearScanOrder()) { + for (LIRInstruction op : lir.getLIRforBlock(b)) { + if (op instanceof AtomicReadAndAddOp) { + usesThreadRegister = true; + assert useHSAILDeoptimization : "cannot use thread register if HSAIL deopt support is disabled"; + break search; + } + } + } // Emit the prologue. HSAILAssembler asm = (HSAILAssembler) crb.asm; @@ -442,7 +468,7 @@ // We're subtracting 1 because we're not making the final gid as a parameter. int nonConstantParamCount = sigParamCount - 1; - boolean isStatic = (Modifier.isStatic(method.getModifiers())); + boolean isStatic = (method.isStatic()); // Determine if this is an object lambda. boolean isObjectLambda = true; @@ -542,18 +568,51 @@ String workItemReg = "$s" + Integer.toString(asRegister(cc.getArgument(nonConstantParamCount)).encoding()); asm.emitString("workitemabsid_u32 " + workItemReg + ", 0;"); - final int offsetToDeopt = getRuntime().getConfig().hsailDeoptOffset; final String deoptInProgressLabel = "@LHandleDeoptInProgress"; if (useHSAILDeoptimization) { - AllocatableValue scratch64 = HSAIL.d16.asValue(Kind.Object); - AllocatableValue scratch32 = HSAIL.s34.asValue(Kind.Int); - HSAILAddress deoptInfoAddr = new HSAILAddressValue(Kind.Int, scratch64, offsetToDeopt).toAddress(); - asm.emitLoadKernelArg(scratch64, asm.getDeoptInfoName(), "u64"); - asm.emitComment("// Check if a deopt has occurred and abort if true before doing any work"); - asm.emitLoadAcquire(scratch32, deoptInfoAddr); - asm.emitCompare(Kind.Int, scratch32, Constant.forInt(0), "ne", false, false); + // Aliases for d16 + RegisterValue d16_deoptInfo = HSAIL.d16.asValue(wordKind); + RegisterValue d16_donorThreads = d16_deoptInfo; + + // Aliases for d17 + RegisterValue d17_donorThreadIndex = HSAIL.d17.asValue(wordKind); + RegisterValue d17_safepointFlagAddrIndex = d17_donorThreadIndex; + + // Aliases for s34 + RegisterValue s34_deoptOccurred = HSAIL.s34.asValue(Kind.Int); + RegisterValue s34_donorThreadIndex = s34_deoptOccurred; + + asm.emitLoadKernelArg(d16_deoptInfo, asm.getDeoptInfoName(), "u64"); + asm.emitComment("// Check if a deopt or safepoint has occurred and abort if true before doing any work"); + + if (useHSAILSafepoints) { + // Load address of _notice_safepoints field + asm.emitLoad(wordKind, d17_safepointFlagAddrIndex, new HSAILAddressValue(wordKind, d16_deoptInfo, config.hsailNoticeSafepointsOffset).toAddress()); + // Load int value from that field + asm.emitLoadAcquire(s34_deoptOccurred, new HSAILAddressValue(Kind.Int, d17_safepointFlagAddrIndex, 0).toAddress()); + asm.emitCompare(Kind.Int, s34_deoptOccurred, Constant.forInt(0), "ne", false, false); + asm.cbr(deoptInProgressLabel); + } + asm.emitLoadAcquire(s34_deoptOccurred, new HSAILAddressValue(Kind.Int, d16_deoptInfo, config.hsailDeoptOccurredOffset).toAddress()); + asm.emitCompare(Kind.Int, s34_deoptOccurred, Constant.forInt(0), "ne", false, false); asm.cbr(deoptInProgressLabel); + // load thread register if needed + if (usesThreadRegister) { + assert HsailDonorThreads.getValue() > 0; + asm.emitLoad(wordKind, d16_donorThreads, new HSAILAddressValue(wordKind, d16_deoptInfo, config.hsailDonorThreadsOffset).toAddress()); + if (HsailDonorThreads.getValue() != 1) { + asm.emitComment("// map workitem to a donor thread"); + asm.emitString(String.format("rem_u32 $%s, %s, %d;", s34_donorThreadIndex.getRegister(), workItemReg, HsailDonorThreads.getValue())); + asm.emitConvert(d17_donorThreadIndex, s34_donorThreadIndex, wordKind, Kind.Int); + asm.emit("mad", d16_donorThreads, d17_donorThreadIndex, Constant.forInt(8), d16_donorThreads); + } else { + // workitem is already mapped to solitary donor thread + } + AllocatableValue threadRegValue = getProviders().getRegisters().getThreadRegister().asValue(wordKind); + asm.emitComment("// $" + getProviders().getRegisters().getThreadRegister() + " will point to a donor thread for this workitem"); + asm.emitLoad(wordKind, threadRegValue, new HSAILAddressValue(wordKind, d16_donorThreads).toAddress()); + } } /* @@ -566,8 +625,8 @@ asm.emitString(spillsegTemplate); // Emit object array load prologue here. if (isObjectLambda) { - boolean useCompressedOops = getRuntime().getConfig().useCompressedOops; - final int arrayElementsOffset = HotSpotGraalRuntime.getArrayBaseOffset(Kind.Object); + boolean useCompressedOops = config.useCompressedOops; + final int arrayElementsOffset = HotSpotGraalRuntime.getArrayBaseOffset(wordKind); String iterationObjArgReg = HSAIL.mapRegister(cc.getArgument(nonConstantParamCount - 1)); // iterationObjArgReg will be the highest $d register in use (it is the last parameter) // so tempReg can be the next higher $d register @@ -586,8 +645,8 @@ // Load u32 into the d 64 reg since it will become an object address asm.emitString("ld_global_u32 " + tmpReg + ", " + "[" + tmpReg + "]" + "; // Load compressed ptr from array"); - long narrowOopBase = getRuntime().getConfig().narrowOopBase; - long narrowOopShift = getRuntime().getConfig().narrowOopShift; + long narrowOopBase = config.narrowOopBase; + long narrowOopShift = config.narrowOopShift; if (narrowOopBase == 0 && narrowOopShift == 0) { // No more calculation to do, mov to target register @@ -629,36 +688,36 @@ // TODO: keep track of whether we need it if (useHSAILDeoptimization) { - final int offsetToDeoptSaveStates = getRuntime().getConfig().hsailSaveStatesOffset0; - final int sizeofKernelDeopt = getRuntime().getConfig().hsailSaveStatesOffset1 - getRuntime().getConfig().hsailSaveStatesOffset0; - final int offsetToNeverRanArray = getRuntime().getConfig().hsailNeverRanArrayOffset; - final int offsetToDeoptNextIndex = getRuntime().getConfig().hsailDeoptNextIndexOffset; - final int offsetToDeoptimizationWorkItem = getRuntime().getConfig().hsailDeoptimizationWorkItem; - final int offsetToDeoptimizationReason = getRuntime().getConfig().hsailDeoptimizationReason; - final int offsetToDeoptimizationFrame = getRuntime().getConfig().hsailDeoptimizationFrame; - final int offsetToFramePc = getRuntime().getConfig().hsailFramePcOffset; - final int offsetToNumSaves = getRuntime().getConfig().hsailFrameNumSRegOffset; - final int offsetToSaveArea = getRuntime().getConfig().hsailFrameSaveAreaOffset; + final int offsetToDeoptSaveStates = config.hsailSaveStatesOffset0; + final int sizeofKernelDeopt = config.hsailSaveStatesOffset1 - config.hsailSaveStatesOffset0; + final int offsetToNeverRanArray = config.hsailNeverRanArrayOffset; + final int offsetToDeoptNextIndex = config.hsailDeoptNextIndexOffset; + final int offsetToDeoptimizationWorkItem = config.hsailDeoptimizationWorkItem; + final int offsetToDeoptimizationReason = config.hsailDeoptimizationReason; + final int offsetToDeoptimizationFrame = config.hsailDeoptimizationFrame; + final int offsetToFramePc = config.hsailFramePcOffset; + final int offsetToNumSaves = config.hsailFrameNumSRegOffset; + final int offsetToSaveArea = config.hsailFrameSaveAreaOffset; - AllocatableValue scratch64 = HSAIL.d16.asValue(Kind.Object); - AllocatableValue cuSaveAreaPtr = HSAIL.d17.asValue(Kind.Object); - AllocatableValue waveMathScratch1 = HSAIL.d18.asValue(Kind.Object); - AllocatableValue waveMathScratch2 = HSAIL.d19.asValue(Kind.Object); + AllocatableValue scratch64 = HSAIL.d16.asValue(wordKind); + AllocatableValue cuSaveAreaPtr = HSAIL.d17.asValue(wordKind); + AllocatableValue waveMathScratch1 = HSAIL.d18.asValue(wordKind); + AllocatableValue waveMathScratch2 = HSAIL.d19.asValue(wordKind); - AllocatableValue actionAndReasonReg = HSAIL.s32.asValue(Kind.Int); - AllocatableValue codeBufferOffsetReg = HSAIL.s33.asValue(Kind.Int); + AllocatableValue actionAndReasonReg = HSAIL.actionAndReasonReg.asValue(Kind.Int); + AllocatableValue codeBufferOffsetReg = HSAIL.codeBufferOffsetReg.asValue(Kind.Int); AllocatableValue scratch32 = HSAIL.s34.asValue(Kind.Int); AllocatableValue workidreg = HSAIL.s35.asValue(Kind.Int); - AllocatableValue dregOopMapReg = HSAIL.s39.asValue(Kind.Int); + AllocatableValue dregOopMapReg = HSAIL.dregOopMapReg.asValue(Kind.Int); HSAILAddress deoptNextIndexAddr = new HSAILAddressValue(Kind.Int, scratch64, offsetToDeoptNextIndex).toAddress(); HSAILAddress neverRanArrayAddr = new HSAILAddressValue(Kind.Int, scratch64, offsetToNeverRanArray).toAddress(); // The just-started lanes that see the deopt flag will jump here asm.emitString0(deoptInProgressLabel + ":\n"); - asm.emitLoad(Kind.Object, waveMathScratch1, neverRanArrayAddr); + asm.emitLoad(wordKind, waveMathScratch1, neverRanArrayAddr); asm.emitWorkItemAbsId(workidreg); - asm.emitConvert(waveMathScratch2, workidreg, Kind.Object, Kind.Int); + asm.emitConvert(waveMathScratch2, workidreg, wordKind, Kind.Int); asm.emit("add", waveMathScratch1, waveMathScratch1, waveMathScratch2); HSAILAddress neverRanStoreAddr = new HSAILAddressValue(Kind.Byte, waveMathScratch1, 0).toAddress(); asm.emitStore(Kind.Byte, Constant.forInt(1), neverRanStoreAddr); @@ -668,7 +727,7 @@ asm.emitString0(asm.getDeoptLabelName() + ":\n"); String labelExit = asm.getDeoptLabelName() + "_Exit"; - HSAILAddress deoptInfoAddr = new HSAILAddressValue(Kind.Int, scratch64, offsetToDeopt).toAddress(); + HSAILAddress deoptInfoAddr = new HSAILAddressValue(Kind.Int, scratch64, config.hsailDeoptOccurredOffset).toAddress(); asm.emitLoadKernelArg(scratch64, asm.getDeoptInfoName(), "u64"); // Set deopt occurred flag @@ -694,7 +753,7 @@ // Store deopt for this workitem into its slot in the HSAILComputeUnitSaveStates array asm.emitComment("// Convert id's for ptr math"); - asm.emitConvert(cuSaveAreaPtr, scratch32, Kind.Object, Kind.Int); + asm.emitConvert(cuSaveAreaPtr, scratch32, wordKind, Kind.Int); asm.emitComment("// multiply by sizeof KernelDeoptArea"); asm.emit("mul", cuSaveAreaPtr, cuSaveAreaPtr, Constant.forInt(sizeofKernelDeopt)); asm.emitComment("// Add computed offset to deoptInfoPtr base"); @@ -725,9 +784,7 @@ asm.emitStore(Kind.Short, dregOopMapReg, dregOopMapAddr); // get the union of registers needed to be saved at the infopoints - // usedRegs array assumes d15 has the highest register number we wish to save - // and initially has all registers as false - boolean[] infoUsedRegs = new boolean[HSAIL.d15.number + 1]; + boolean[] infoUsedRegs = new boolean[HSAIL.threadRegister.number + 1]; List infoList = crb.compilationResult.getInfopoints(); for (Infopoint info : infoList) { BytecodeFrame frame = info.debugInfo.frame(); @@ -784,10 +841,10 @@ ExternalCompilationResult compilationResult = (ExternalCompilationResult) crb.compilationResult; HSAILHotSpotLIRGenerationResult lirGenRes = ((HSAILCompilationResultBuilder) crb).lirGenRes; - compilationResult.setHostGraph(prepareHostGraph(method, lirGenRes.getDeopts(), getProviders(), getRuntime().getConfig())); + compilationResult.setHostGraph(prepareHostGraph(method, lirGenRes.getDeopts(), getProviders(), config)); } - private static StructuredGraph prepareHostGraph(ResolvedJavaMethod method, List deopts, HotSpotProviders providers, HotSpotVMConfig config) { + private static StructuredGraph prepareHostGraph(ResolvedJavaMethod method, List deopts, HotSpotProviders providers, HotSpotVMConfig config) { if (deopts.isEmpty()) { return null; } @@ -796,17 +853,17 @@ ParameterNode hsailFrame = hostGraph.unique(new ParameterNode(1, StampFactory.forKind(providers.getCodeCache().getTarget().wordKind))); ParameterNode reasonAndAction = hostGraph.unique(new ParameterNode(2, StampFactory.intValue())); ParameterNode speculation = hostGraph.unique(new ParameterNode(3, StampFactory.object())); - AbstractBeginNode[] branches = new AbstractBeginNode[deopts.size() + 1]; + BeginNode[] branches = new BeginNode[deopts.size() + 1]; int[] keys = new int[deopts.size()]; int[] keySuccessors = new int[deopts.size() + 1]; double[] keyProbabilities = new double[deopts.size() + 1]; int i = 0; - Collections.sort(deopts, new Comparator() { - public int compare(DeoptimizeOp o1, DeoptimizeOp o2) { + Collections.sort(deopts, new Comparator() { + public int compare(DeoptimizingOp o1, DeoptimizingOp o2) { return o1.getCodeBufferPos() - o2.getCodeBufferPos(); } }); - for (DeoptimizeOp deopt : deopts) { + for (DeoptimizingOp deopt : deopts) { keySuccessors[i] = i; keyProbabilities[i] = 1.0 / deopts.size(); keys[i] = deopt.getCodeBufferPos(); @@ -828,15 +885,14 @@ return hostGraph; } - private static AbstractBeginNode createHostCrashBranch(StructuredGraph hostGraph, ValueNode deoptId) { + private static BeginNode createHostCrashBranch(StructuredGraph hostGraph, ValueNode deoptId) { VMErrorNode vmError = hostGraph.add(new VMErrorNode("Error in HSAIL deopt. DeoptId=%d", deoptId)); // ConvertNode.convert(hostGraph, Kind.Long, deoptId))); vmError.setNext(hostGraph.add(new ReturnNode(ConstantNode.defaultForKind(hostGraph.method().getSignature().getReturnKind(), hostGraph)))); return BeginNode.begin(vmError); } - private static AbstractBeginNode createHostDeoptBranch(DeoptimizeOp deopt, ParameterNode hsailFrame, ValueNode reasonAndAction, ValueNode speculation, HotSpotProviders providers, - HotSpotVMConfig config) { + private static BeginNode createHostDeoptBranch(DeoptimizingOp deopt, ParameterNode hsailFrame, ValueNode reasonAndAction, ValueNode speculation, HotSpotProviders providers, HotSpotVMConfig config) { BeginNode branch = hsailFrame.graph().add(new BeginNode()); DynamicDeoptimizeNode deoptimization = hsailFrame.graph().add(new DynamicDeoptimizeNode(reasonAndAction, speculation)); deoptimization.setStateBefore(createFrameState(deopt.getFrameState().topFrame, hsailFrame, providers, config)); @@ -868,7 +924,7 @@ return frameState; } - @SuppressWarnings({"unused"}) + @SuppressWarnings("unused") private static MonitorIdNode getMonitorIdForHotSpotMonitorValueFromFrame(HotSpotMonitorValue lockValue, ParameterNode hsailFrame, StructuredGraph hsailGraph) { if (lockValue.isEliminated()) { return null; @@ -910,7 +966,7 @@ int longSize = providers.getCodeCache().getTarget().arch.getSizeInBytes(Kind.Long); long offset = config.hsailFrameSaveAreaOffset + longSize * (regNumber - HSAIL.d0.number); LocationNode numSRegsLocation = ConstantLocationNode.create(FINAL_LOCATION, Kind.Byte, config.hsailFrameNumSRegOffset, hostGraph); - ValueNode numSRegs = hostGraph.unique(new FloatingReadNode(hsailFrame, numSRegsLocation, null, StampFactory.forInteger(8, false))); + ValueNode numSRegs = hostGraph.unique(new FloatingReadNode(hsailFrame, numSRegsLocation, null, StampFactory.forInteger(8))); numSRegs = SignExtendNode.convert(numSRegs, StampFactory.forKind(Kind.Byte)); location = IndexedLocationNode.create(FINAL_LOCATION, valueKind, offset, numSRegs, hostGraph, 4); } else { diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.hotspot.hsail/src/com/oracle/graal/hotspot/hsail/HSAILHotSpotBackendFactory.java --- a/graal/com.oracle.graal.hotspot.hsail/src/com/oracle/graal/hotspot/hsail/HSAILHotSpotBackendFactory.java Fri Apr 25 16:21:07 2014 +0200 +++ b/graal/com.oracle.graal.hotspot.hsail/src/com/oracle/graal/hotspot/hsail/HSAILHotSpotBackendFactory.java Mon Apr 28 11:18:15 2014 +0200 @@ -28,10 +28,10 @@ import com.oracle.graal.hotspot.*; import com.oracle.graal.hotspot.meta.*; import com.oracle.graal.hsail.*; -import com.oracle.graal.java.*; import com.oracle.graal.nodes.spi.*; import com.oracle.graal.phases.tiers.*; import com.oracle.graal.phases.util.*; +import com.oracle.graal.hotspot.hsail.replacements.*; @ServiceProvider(HotSpotBackendFactory.class) public class HSAILHotSpotBackendFactory implements HotSpotBackendFactory { @@ -44,7 +44,7 @@ public HSAILHotSpotBackend createBackend(HotSpotGraalRuntime runtime, HotSpotBackend hostBackend) { HotSpotProviders host = hostBackend.getProviders(); - HotSpotRegisters registers = new HotSpotRegisters(Register.None, Register.None, Register.None); + HotSpotRegisters registers = new HotSpotRegisters(HSAIL.threadRegister, Register.None, Register.None); HotSpotMetaAccessProvider metaAccess = host.getMetaAccess(); HSAILHotSpotCodeCacheProvider codeCache = new HSAILHotSpotCodeCacheProvider(runtime, createTarget()); ConstantReflectionProvider constantReflection = host.getConstantReflection(); @@ -56,9 +56,12 @@ Providers p = new Providers(metaAccess, codeCache, constantReflection, foreignCalls, lowerer, null); Replacements replacements = new HSAILHotSpotReplacementsImpl(p, host.getSnippetReflection(), assumptions, codeCache.getTarget(), host.getReplacements()); HotSpotDisassemblerProvider disassembler = host.getDisassembler(); - SuitesProvider suites = new DefaultSuitesProvider(); + SuitesProvider suites = new HotSpotSuitesProvider(runtime); HotSpotProviders providers = new HotSpotProviders(metaAccess, codeCache, constantReflection, foreignCalls, lowerer, replacements, disassembler, suites, registers, host.getSnippetReflection()); + // pass registers info down to ReplacementsUtil (maybe a better way to do this?) + HSAILHotSpotReplacementsUtil.initialize(providers.getRegisters()); + return new HSAILHotSpotBackend(runtime, providers); } diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.hotspot.hsail/src/com/oracle/graal/hotspot/hsail/HSAILHotSpotLIRGenerationResult.java --- a/graal/com.oracle.graal.hotspot.hsail/src/com/oracle/graal/hotspot/hsail/HSAILHotSpotLIRGenerationResult.java Fri Apr 25 16:21:07 2014 +0200 +++ b/graal/com.oracle.graal.hotspot.hsail/src/com/oracle/graal/hotspot/hsail/HSAILHotSpotLIRGenerationResult.java Mon Apr 28 11:18:15 2014 +0200 @@ -24,23 +24,23 @@ import java.util.*; -import com.oracle.graal.compiler.gen.*; import com.oracle.graal.lir.*; -import com.oracle.graal.lir.hsail.HSAILControlFlow.DeoptimizeOp; +import com.oracle.graal.lir.gen.*; +import com.oracle.graal.lir.hsail.HSAILControlFlow.DeoptimizingOp; public class HSAILHotSpotLIRGenerationResult extends LIRGenerationResultBase { - private List deopts = new ArrayList<>(); + private List deopts = new ArrayList<>(); public HSAILHotSpotLIRGenerationResult(LIR lir, FrameMap frameMap) { super(lir, frameMap); } - public List getDeopts() { + public List getDeopts() { return deopts; } - public void addDeopt(DeoptimizeOp deopt) { + public void addDeopt(DeoptimizingOp deopt) { deopts.add(deopt); } diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.hotspot.hsail/src/com/oracle/graal/hotspot/hsail/HSAILHotSpotLIRGenerator.java --- a/graal/com.oracle.graal.hotspot.hsail/src/com/oracle/graal/hotspot/hsail/HSAILHotSpotLIRGenerator.java Fri Apr 25 16:21:07 2014 +0200 +++ b/graal/com.oracle.graal.hotspot.hsail/src/com/oracle/graal/hotspot/hsail/HSAILHotSpotLIRGenerator.java Mon Apr 28 11:18:15 2014 +0200 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 2014, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -27,14 +27,16 @@ import com.oracle.graal.api.code.*; import com.oracle.graal.api.meta.*; -import com.oracle.graal.compiler.gen.*; +import com.oracle.graal.compiler.common.*; +import com.oracle.graal.compiler.common.calc.*; import com.oracle.graal.compiler.hsail.*; -import com.oracle.graal.graph.*; import com.oracle.graal.hotspot.*; import com.oracle.graal.hotspot.HotSpotVMConfig.CompressEncoding; import com.oracle.graal.hotspot.meta.*; import com.oracle.graal.hotspot.nodes.type.*; import com.oracle.graal.lir.*; +import com.oracle.graal.lir.StandardOp.SaveRegistersOp; +import com.oracle.graal.lir.gen.*; import com.oracle.graal.lir.hsail.*; import com.oracle.graal.lir.hsail.HSAILControlFlow.CondMoveOp; import com.oracle.graal.lir.hsail.HSAILControlFlow.DeoptimizeOp; @@ -42,16 +44,11 @@ import com.oracle.graal.lir.hsail.HSAILControlFlow.ForeignCall2ArgOp; import com.oracle.graal.lir.hsail.HSAILControlFlow.ForeignCallNoArgOp; import com.oracle.graal.lir.hsail.HSAILMove.CompareAndSwapOp; -import com.oracle.graal.lir.hsail.HSAILMove.LoadCompressedPointer; import com.oracle.graal.lir.hsail.HSAILMove.LoadOp; import com.oracle.graal.lir.hsail.HSAILMove.MoveFromRegOp; import com.oracle.graal.lir.hsail.HSAILMove.MoveToRegOp; -import com.oracle.graal.lir.hsail.HSAILMove.StoreCompressedPointer; import com.oracle.graal.lir.hsail.HSAILMove.StoreConstantOp; import com.oracle.graal.lir.hsail.HSAILMove.StoreOp; -import com.oracle.graal.nodes.*; -import com.oracle.graal.nodes.calc.*; -import com.oracle.graal.nodes.extended.*; import com.oracle.graal.phases.util.*; /** @@ -95,22 +92,11 @@ return config.narrowKlassBase; } - private static boolean isCompressCandidate(Access access) { - return access != null && access.isCompressible(); - } - @Override public boolean canStoreConstant(Constant c, boolean isCompressed) { return true; } - /** - * Returns whether or not the input access should be (de)compressed. - */ - private boolean isCompressedOperation(PlatformKind kind, Access access) { - return access != null && access.isCompressible() && ((kind == Kind.Long && config.useCompressedClassPointers) || (kind == Kind.Object && config.useCompressedOops)); - } - private static Kind getMemoryKind(PlatformKind kind) { if (kind == NarrowOopStamp.NarrowOop) { return Kind.Int; @@ -120,20 +106,10 @@ } @Override - public Variable emitLoad(PlatformKind kind, Value address, Access access) { + public Variable emitLoad(PlatformKind kind, Value address, LIRFrameState state) { HSAILAddressValue loadAddress = asAddressValue(address); Variable result = newVariable(kind); - LIRFrameState state = null; - if (access instanceof DeoptimizingNode) { - state = state((DeoptimizingNode) access); - } - if (isCompressCandidate(access) && config.useCompressedOops && kind == Kind.Object) { - Variable scratch = newVariable(Kind.Long); - append(new LoadCompressedPointer(Kind.Object, result, scratch, loadAddress, state, getNarrowOopBase(), getNarrowOopShift(), getLogMinObjectAlignment())); - } else if (isCompressCandidate(access) && config.useCompressedClassPointers && kind == Kind.Long) { - Variable scratch = newVariable(Kind.Long); - append(new LoadCompressedPointer(Kind.Object, result, scratch, loadAddress, state, getNarrowKlassBase(), getNarrowKlassShift(), getLogKlassAlignment())); - } else if (kind == NarrowOopStamp.NarrowOop) { + if (kind == NarrowOopStamp.NarrowOop) { append(new LoadOp(Kind.Int, result, loadAddress, state)); } else { append(new LoadOp(getMemoryKind(kind), result, loadAddress, state)); @@ -142,40 +118,17 @@ } @Override - public void emitStore(PlatformKind kind, Value address, Value inputVal, Access access) { + public void emitStore(PlatformKind kind, Value address, Value inputVal, LIRFrameState state) { HSAILAddressValue storeAddress = asAddressValue(address); - LIRFrameState state = null; - if (access instanceof DeoptimizingNode) { - state = state((DeoptimizingNode) access); - } - boolean isCompressed = isCompressedOperation(kind, access); if (isConstant(inputVal)) { Constant c = asConstant(inputVal); - if (canStoreConstant(c, isCompressed)) { - if (isCompressed) { - if ((c.getKind() == Kind.Object) && c.isNull()) { - append(new StoreConstantOp(Kind.Int, storeAddress, Constant.forInt(0), state)); - } else if (c.getKind() == Kind.Long) { - Constant value = compress(c, config.getKlassEncoding()); - append(new StoreConstantOp(Kind.Int, storeAddress, value, state)); - } else { - throw GraalInternalError.shouldNotReachHere("can't handle: " + access); - } - return; - } else { - append(new StoreConstantOp(getMemoryKind(kind), storeAddress, c, state)); - return; - } + if (canStoreConstant(c, false)) { + append(new StoreConstantOp(getMemoryKind(kind), storeAddress, c, state)); + return; } } Variable input = load(inputVal); - if (isCompressCandidate(access) && config.useCompressedOops && kind == Kind.Object) { - Variable scratch = newVariable(Kind.Long); - append(new StoreCompressedPointer(Kind.Object, storeAddress, input, scratch, state, getNarrowOopBase(), getNarrowOopShift(), getLogMinObjectAlignment())); - } else if (isCompressCandidate(access) && config.useCompressedClassPointers && kind == Kind.Long) { - Variable scratch = newVariable(Kind.Long); - append(new StoreCompressedPointer(Kind.Object, storeAddress, input, scratch, state, getNarrowKlassBase(), getNarrowKlassShift(), getLogKlassAlignment())); - } else if (kind == NarrowOopStamp.NarrowOop) { + if (kind == NarrowOopStamp.NarrowOop) { append(new StoreOp(Kind.Int, storeAddress, input, state)); } else { append(new StoreOp(getMemoryKind(kind), storeAddress, input, state)); @@ -199,8 +152,28 @@ } @Override - public void emitDeoptimize(Value actionAndReason, Value failedSpeculation, DeoptimizingNode deopting) { - emitDeoptimizeInner(actionAndReason, state(deopting), "emitDeoptimize"); + public Value emitAtomicReadAndAdd(Value address, Value delta) { + PlatformKind kind = delta.getPlatformKind(); + Kind memKind = getMemoryKind(kind); + Variable result = newVariable(kind); + HSAILAddressValue addressValue = asAddressValue(address); + append(new HSAILMove.AtomicReadAndAddOp(memKind, result, addressValue, asAllocatable(delta))); + return result; + } + + @Override + public Value emitAtomicReadAndWrite(Value address, Value newValue) { + PlatformKind kind = newValue.getPlatformKind(); + Kind memKind = getMemoryKind(kind); + Variable result = newVariable(kind); + HSAILAddressValue addressValue = asAddressValue(address); + append(new HSAILMove.AtomicReadAndWriteOp(memKind, result, addressValue, asAllocatable(newValue))); + return result; + } + + @Override + public void emitDeoptimize(Value actionAndReason, Value failedSpeculation, LIRFrameState state) { + emitDeoptimizeInner(actionAndReason, state, "emitDeoptimize"); } /*** @@ -218,7 +191,7 @@ * emitting a comment as to what Foreign call they would have made. */ @Override - public Variable emitForeignCall(ForeignCallLinkage linkage, DeoptimizingNode info, Value... args) { + public Variable emitForeignCall(ForeignCallLinkage linkage, LIRFrameState state, Value... args) { Variable result = newVariable(Kind.Object); // linkage.getDescriptor().getResultType()); // to make the LIRVerifier happy, we move any constants into registers @@ -283,15 +256,15 @@ } public void emitTailcall(Value[] args, Value address) { - throw GraalInternalError.shouldNotReachHere("NYI"); + throw GraalInternalError.unimplemented(); } public void emitDeoptimizeCaller(DeoptimizationAction action, DeoptimizationReason reason) { - throw GraalInternalError.shouldNotReachHere("NYI"); + throw GraalInternalError.unimplemented(); } public StackSlot getLockSlot(int lockDepth) { - throw GraalInternalError.shouldNotReachHere("NYI"); + throw GraalInternalError.unimplemented(); } @Override @@ -307,4 +280,32 @@ append(new HSAILMove.UncompressPointer(result, asAllocatable(pointer), encoding.base, encoding.shift, encoding.alignment, nonNull)); return result; } + + public void emitLeaveCurrentStackFrame() { + throw GraalInternalError.unimplemented(); + } + + public void emitLeaveDeoptimizedStackFrame(Value frameSize, Value initialInfo) { + throw GraalInternalError.unimplemented(); + } + + public void emitEnterUnpackFramesStackFrame(Value framePc, Value senderSp, Value senderFp) { + throw GraalInternalError.unimplemented(); + } + + public void emitLeaveUnpackFramesStackFrame() { + throw GraalInternalError.unimplemented(); + } + + public SaveRegistersOp emitSaveAllRegisters() { + throw GraalInternalError.unimplemented(); + } + + public void emitPushInterpreterFrame(Value frameSize, Value framePc, Value senderSp, Value initialInfo) { + throw GraalInternalError.unimplemented(); + } + + public Value emitUncommonTrapCall(Value trapRequest, SaveRegistersOp saveRegisterOp) { + throw GraalInternalError.unimplemented(); + } } diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.hotspot.hsail/src/com/oracle/graal/hotspot/hsail/HSAILHotSpotLoweringProvider.java --- a/graal/com.oracle.graal.hotspot.hsail/src/com/oracle/graal/hotspot/hsail/HSAILHotSpotLoweringProvider.java Fri Apr 25 16:21:07 2014 +0200 +++ b/graal/com.oracle.graal.hotspot.hsail/src/com/oracle/graal/hotspot/hsail/HSAILHotSpotLoweringProvider.java Mon Apr 28 11:18:15 2014 +0200 @@ -22,41 +22,59 @@ */ package com.oracle.graal.hotspot.hsail; -import java.util.*; - import com.oracle.graal.api.code.*; import com.oracle.graal.api.meta.*; +import com.oracle.graal.compiler.common.*; import com.oracle.graal.graph.*; import com.oracle.graal.hotspot.*; import com.oracle.graal.hotspot.meta.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.calc.*; +import com.oracle.graal.nodes.spi.*; import com.oracle.graal.nodes.extended.*; import com.oracle.graal.nodes.java.*; -import com.oracle.graal.nodes.spi.*; +import com.oracle.graal.hotspot.hsail.replacements.*; + +import java.util.HashMap; public class HSAILHotSpotLoweringProvider extends DefaultHotSpotLoweringProvider { - abstract static class LoweringStrategy { + private HSAILNewObjectSnippets.Templates hsailNewObjectSnippets; + + abstract class LoweringStrategy { abstract void lower(Node n, LoweringTool tool); } - static LoweringStrategy PassThruStrategy = new LoweringStrategy() { + LoweringStrategy PassThruStrategy = new LoweringStrategy() { @Override void lower(Node n, LoweringTool tool) { return; } }; - static LoweringStrategy RejectStrategy = new LoweringStrategy() { + LoweringStrategy RejectStrategy = new LoweringStrategy() { @Override void lower(Node n, LoweringTool tool) { throw new GraalInternalError("Node implementing Lowerable not handled in HSAIL Backend: " + n); } }; + LoweringStrategy NewObjectStrategy = new LoweringStrategy() { + @Override + void lower(Node n, LoweringTool tool) { + StructuredGraph graph = (StructuredGraph) n.graph(); + if (graph.getGuardsStage() == StructuredGraph.GuardsStage.AFTER_FSA) { + if (n instanceof NewInstanceNode) { + hsailNewObjectSnippets.lower((NewInstanceNode) n, tool); + } else if (n instanceof NewArrayNode) { + hsailNewObjectSnippets.lower((NewArrayNode) n, tool); + } + } + } + }; + // strategy to replace an UnwindNode with a DeoptNode - static LoweringStrategy UnwindNodeStrategy = new LoweringStrategy() { + LoweringStrategy UnwindNodeStrategy = new LoweringStrategy() { @Override void lower(Node n, LoweringTool tool) { StructuredGraph graph = (StructuredGraph) n.graph(); @@ -85,12 +103,13 @@ } }; - private static HashMap, LoweringStrategy> strategyMap = new HashMap<>(); - static { + private HashMap, LoweringStrategy> strategyMap = new HashMap<>(); + + void initStrategyMap() { strategyMap.put(ConvertNode.class, PassThruStrategy); strategyMap.put(FloatConvertNode.class, PassThruStrategy); - strategyMap.put(NewInstanceNode.class, RejectStrategy); - strategyMap.put(NewArrayNode.class, RejectStrategy); + strategyMap.put(NewInstanceNode.class, NewObjectStrategy); + strategyMap.put(NewArrayNode.class, NewObjectStrategy); strategyMap.put(NewMultiArrayNode.class, RejectStrategy); strategyMap.put(DynamicNewArrayNode.class, RejectStrategy); strategyMap.put(MonitorEnterNode.class, RejectStrategy); @@ -98,12 +117,20 @@ strategyMap.put(UnwindNode.class, UnwindNodeStrategy); } - private static LoweringStrategy getStrategy(Node n) { + private LoweringStrategy getStrategy(Node n) { return strategyMap.get(n.getClass()); } public HSAILHotSpotLoweringProvider(HotSpotGraalRuntime runtime, MetaAccessProvider metaAccess, ForeignCallsProvider foreignCalls, HotSpotRegistersProvider registers) { super(runtime, metaAccess, foreignCalls, registers); + initStrategyMap(); + } + + @Override + public void initialize(HotSpotProviders providers, HotSpotVMConfig config) { + super.initialize(providers, config); + TargetDescription target = providers.getCodeCache().getTarget(); + hsailNewObjectSnippets = new HSAILNewObjectSnippets.Templates(providers, target); } @Override diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.hotspot.hsail/src/com/oracle/graal/hotspot/hsail/HSAILHotSpotNodeLIRBuilder.java --- a/graal/com.oracle.graal.hotspot.hsail/src/com/oracle/graal/hotspot/hsail/HSAILHotSpotNodeLIRBuilder.java Fri Apr 25 16:21:07 2014 +0200 +++ b/graal/com.oracle.graal.hotspot.hsail/src/com/oracle/graal/hotspot/hsail/HSAILHotSpotNodeLIRBuilder.java Mon Apr 28 11:18:15 2014 +0200 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 2014, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -23,21 +23,28 @@ package com.oracle.graal.hotspot.hsail; +import com.oracle.graal.api.code.*; import com.oracle.graal.api.meta.*; -import com.oracle.graal.compiler.gen.*; +import com.oracle.graal.asm.*; +import com.oracle.graal.compiler.common.*; import com.oracle.graal.compiler.hsail.*; -import com.oracle.graal.graph.*; +import com.oracle.graal.debug.*; +import com.oracle.graal.hotspot.*; import com.oracle.graal.hotspot.HotSpotVMConfig.CompressEncoding; import com.oracle.graal.hotspot.meta.*; import com.oracle.graal.hotspot.nodes.*; +import com.oracle.graal.lir.*; +import com.oracle.graal.lir.gen.*; +import com.oracle.graal.lir.hsail.*; +import com.oracle.graal.lir.hsail.HSAILMove.CompareAndSwapOp; import com.oracle.graal.nodes.*; /** * The HotSpot specific portion of the HSAIL LIR generator. */ -public class HSAILHotSpotNodeLIRBuilder extends HSAILNodeLIRBuilder { +public class HSAILHotSpotNodeLIRBuilder extends HSAILNodeLIRBuilder implements HotSpotNodeLIRBuilder { - public HSAILHotSpotNodeLIRBuilder(StructuredGraph graph, LIRGenerator lirGen) { + public HSAILHotSpotNodeLIRBuilder(StructuredGraph graph, LIRGeneratorTool lirGen) { super(graph, lirGen); } @@ -50,6 +57,10 @@ } } + private HSAILHotSpotLIRGenerator getGen() { + return (HSAILHotSpotLIRGenerator) gen; + } + /** * @return a compressed version of the incoming constant lifted from AMD64HotSpotLIRGenerator */ @@ -65,4 +76,56 @@ throw GraalInternalError.shouldNotReachHere(); } } + + public void visitDirectCompareAndSwap(DirectCompareAndSwapNode x) { + Kind kind = x.newValue().getKind(); + assert kind == x.expectedValue().getKind(); + + Variable expected = getGen().load(operand(x.expectedValue())); + Variable newVal = getGen().load(operand(x.newValue())); + + int disp = 0; + HSAILAddressValue address; + Value index = operand(x.offset()); + if (ValueUtil.isConstant(index) && NumUtil.isInt(ValueUtil.asConstant(index).asLong() + disp)) { + assert !getGen().getCodeCache().needsDataPatch(ValueUtil.asConstant(index)); + disp += (int) ValueUtil.asConstant(index).asLong(); + address = new HSAILAddressValue(kind, getGen().load(operand(x.object())), disp); + } else { + throw GraalInternalError.shouldNotReachHere("NYI"); + } + + Variable casResult = newVariable(kind); + append(new CompareAndSwapOp(kind, casResult, address, expected, newVal)); + + setResult(x, casResult); + } + + @Override + public void visitSafepointNode(SafepointNode i) { + HotSpotVMConfig config = getGen().config; + if (config.useHSAILSafepoints == true) { + LIRFrameState info = state(i); + HSAILHotSpotSafepointOp safepoint = new HSAILHotSpotSafepointOp(info, config, this); + ((HSAILHotSpotLIRGenerationResult) getGen().getResult()).addDeopt(safepoint); + append(safepoint); + } else { + Debug.log("HSAIL safepoints turned off"); + } + } + + @Override + public void emitPrefetchAllocate(ValueNode address, ValueNode distance) { + // nop + } + + @Override + public void emitPatchReturnAddress(ValueNode address) { + throw GraalInternalError.unimplemented(); + } + + @Override + public void emitJumpToExceptionHandlerInCaller(ValueNode handlerInCallerPc, ValueNode exception, ValueNode exceptionPc) { + throw GraalInternalError.unimplemented(); + } } diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.hotspot.hsail/src/com/oracle/graal/hotspot/hsail/HSAILHotSpotRegisterConfig.java --- a/graal/com.oracle.graal.hotspot.hsail/src/com/oracle/graal/hotspot/hsail/HSAILHotSpotRegisterConfig.java Fri Apr 25 16:21:07 2014 +0200 +++ b/graal/com.oracle.graal.hotspot.hsail/src/com/oracle/graal/hotspot/hsail/HSAILHotSpotRegisterConfig.java Mon Apr 28 11:18:15 2014 +0200 @@ -28,7 +28,7 @@ import com.oracle.graal.api.code.*; import com.oracle.graal.api.code.CallingConvention.Type; import com.oracle.graal.api.meta.*; -import com.oracle.graal.graph.*; +import com.oracle.graal.compiler.common.*; import com.oracle.graal.hotspot.nodes.type.*; import com.oracle.graal.hsail.*; diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.hotspot.hsail/src/com/oracle/graal/hotspot/hsail/HSAILHotSpotSafepointOp.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.hotspot.hsail/src/com/oracle/graal/hotspot/hsail/HSAILHotSpotSafepointOp.java Mon Apr 28 11:18:15 2014 +0200 @@ -0,0 +1,112 @@ +/* + * 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.hsail; + +import static com.oracle.graal.api.code.ValueUtil.*; + +import com.oracle.graal.api.code.*; +import com.oracle.graal.api.meta.*; +import com.oracle.graal.asm.hsail.*; +import com.oracle.graal.hotspot.*; +import com.oracle.graal.hsail.*; +import com.oracle.graal.lir.*; +import com.oracle.graal.lir.asm.*; +import com.oracle.graal.lir.hsail.*; +import com.oracle.graal.nodes.spi.*; + +/** + * Emits a safepoint deoptimization from HSA back to CPU. + */ +@Opcode("SAFEPOINT") +public class HSAILHotSpotSafepointOp extends HSAILLIRInstruction implements HSAILControlFlow.DeoptimizingOp { + private Constant actionAndReason; + @State protected LIRFrameState frameState; + protected int codeBufferPos = -1; + protected int dregOopMap = 0; + final int offsetToNoticeSafepoints; + + public HSAILHotSpotSafepointOp(LIRFrameState state, HotSpotVMConfig config, NodeLIRBuilderTool tool) { + actionAndReason = tool.getLIRGeneratorTool().getMetaAccess().encodeDeoptActionAndReason(DeoptimizationAction.None, DeoptimizationReason.None, 0); + frameState = state; + offsetToNoticeSafepoints = config.hsailNoticeSafepointsOffset; + } + + @Override + public void emitCode(CompilationResultBuilder crb, HSAILAssembler masm) { + + // get a unique codeBuffer position + // when we save our state, we will save this as well (it can be used as a key to get the + // debugInfo) + codeBufferPos = masm.position(); + + masm.emitComment(" /* HSAIL safepoint bci=" + frameState.debugInfo().getBytecodePosition().getBCI() + ", frameState=" + frameState + " */"); + String afterSafepointLabel = "@LAfterSafepoint_at_pos_" + codeBufferPos; + + AllocatableValue scratch64 = HSAIL.d16.asValue(Kind.Object); + AllocatableValue spAddrReg = HSAIL.d17.asValue(Kind.Object); + AllocatableValue scratch32 = HSAIL.s34.asValue(Kind.Int); + masm.emitLoadKernelArg(scratch64, masm.getDeoptInfoName(), "u64"); + + // Build address of noticeSafepoints field + HSAILAddress noticeSafepointsAddr = new HSAILAddressValue(Kind.Object, scratch64, offsetToNoticeSafepoints).toAddress(); + masm.emitLoad(Kind.Object, spAddrReg, noticeSafepointsAddr); + + // Load int value from that field + HSAILAddress noticeSafepointsIntAddr = new HSAILAddressValue(Kind.Int, spAddrReg, 0).toAddress(); + masm.emitLoadAcquire(scratch32, noticeSafepointsIntAddr); + masm.emitCompare(Kind.Int, scratch32, Constant.forInt(0), "eq", false, false); + masm.cbr(afterSafepointLabel); + + BytecodeFrame frame = frameState.debugInfo().frame(); + for (int i = 0; i < frame.numLocals + frame.numStack; i++) { + Value val = frame.values[i]; + if (isLegal(val) && isRegister(val)) { + Register reg = asRegister(val); + if (val.getKind() == Kind.Object) { + dregOopMap |= 1 << (reg.encoding()); + } + } + } + + AllocatableValue actionAndReasonReg = HSAIL.actionAndReasonReg.asValue(Kind.Int); + AllocatableValue codeBufferOffsetReg = HSAIL.codeBufferOffsetReg.asValue(Kind.Int); + AllocatableValue dregOopMapReg = HSAIL.dregOopMapReg.asValue(Kind.Int); + masm.emitMov(Kind.Int, actionAndReasonReg, actionAndReason); + masm.emitMov(Kind.Int, codeBufferOffsetReg, Constant.forInt(codeBufferPos)); + masm.emitMov(Kind.Int, dregOopMapReg, Constant.forInt(dregOopMap)); + masm.emitJumpToLabelName(masm.getDeoptLabelName()); + + masm.emitString0(afterSafepointLabel + ":\n"); + + // now record the debuginfo + crb.recordInfopoint(codeBufferPos, frameState, InfopointReason.SAFEPOINT); + } + + public LIRFrameState getFrameState() { + return frameState; + } + + public int getCodeBufferPos() { + return codeBufferPos; + } +} \ No newline at end of file diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.hotspot.hsail/src/com/oracle/graal/hotspot/hsail/replacements/HSAILHotSpotReplacementsUtil.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.hotspot.hsail/src/com/oracle/graal/hotspot/hsail/replacements/HSAILHotSpotReplacementsUtil.java Mon Apr 28 11:18:15 2014 +0200 @@ -0,0 +1,73 @@ +/* + * Copyright (c) 2012, 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.graal.hotspot.hsail.replacements; + +import com.oracle.graal.api.code.*; +import com.oracle.graal.api.meta.*; +import com.oracle.graal.nodes.java.*; +import com.oracle.graal.replacements.Snippet.Fold; +import com.oracle.graal.word.*; +import com.oracle.graal.hotspot.replacements.HotSpotReplacementsUtil; +import com.oracle.graal.hotspot.meta.*; + +//JaCoCo Exclude + +/** + * A collection of methods used in HSAIL-specific snippets and substitutions. + */ +public class HSAILHotSpotReplacementsUtil extends HotSpotReplacementsUtil { + + private static HotSpotRegistersProvider hsailRegisters; + + public static void initialize(HotSpotRegistersProvider registers) { + hsailRegisters = registers; + } + + /** + * Gets the value of the thread register as a Word. + */ + public static Word thread() { + return registerAsWord(threadRegister(), true, false); + } + + @Fold + public static Register threadRegister() { + return hsailRegisters.getThreadRegister(); + } + + public static Word atomicGetAndAddTlabTop(Word thread, int size) { + return Word.unsigned(AtomicReadAndAddNode.getAndAddLong(null, thread.rawValue() + threadTlabTopOffset(), size, TLAB_TOP_LOCATION)); + } + + public static final LocationIdentity TLAB_PFTOP_LOCATION = new NamedLocationIdentity("TlabPfTop"); + + @Fold + public static int threadTlabPfTopOffset() { + return config().threadTlabPfTopOffset(); + } + + public static void writeTlabPfTop(Word thread, Word val) { + thread.writeWord(threadTlabPfTopOffset(), val, TLAB_PFTOP_LOCATION); + } + +} diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.hotspot.hsail/src/com/oracle/graal/hotspot/hsail/replacements/HSAILNewObjectSnippets.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.hotspot.hsail/src/com/oracle/graal/hotspot/hsail/replacements/HSAILNewObjectSnippets.java Mon Apr 28 11:18:15 2014 +0200 @@ -0,0 +1,255 @@ +/* + * 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.hsail.replacements; + +import static com.oracle.graal.api.code.UnsignedMath.*; +import static com.oracle.graal.compiler.common.GraalOptions.*; +import static com.oracle.graal.hotspot.hsail.replacements.HSAILHotSpotReplacementsUtil.*; +import static com.oracle.graal.hotspot.hsail.replacements.HSAILNewObjectSnippets.Options.*; +import static com.oracle.graal.nodes.PiArrayNode.*; +import static com.oracle.graal.nodes.extended.BranchProbabilityNode.*; +import static com.oracle.graal.replacements.SnippetTemplate.*; + +import com.oracle.graal.api.code.*; +import com.oracle.graal.api.meta.*; +import com.oracle.graal.compiler.common.type.*; +import com.oracle.graal.debug.*; +import com.oracle.graal.hotspot.*; +import com.oracle.graal.hotspot.meta.*; +import com.oracle.graal.hotspot.replacements.*; +import com.oracle.graal.hotspot.stubs.*; +import com.oracle.graal.nodes.*; +import com.oracle.graal.nodes.java.*; +import com.oracle.graal.nodes.spi.*; +import com.oracle.graal.options.*; +import com.oracle.graal.replacements.*; +import com.oracle.graal.replacements.Snippet.ConstantParameter; +import com.oracle.graal.replacements.SnippetTemplate.AbstractTemplates; +import com.oracle.graal.replacements.SnippetTemplate.Arguments; +import com.oracle.graal.replacements.SnippetTemplate.SnippetInfo; +import com.oracle.graal.word.*; + +/** + * HSAIL-specific Snippets used for implementing NEW and NEWARRAY. + */ +public class HSAILNewObjectSnippets extends NewObjectSnippets { + + static public class Options { + + // @formatter:off + @Option(help = "In HSAIL allocation, allow allocation from eden as fallback if TLAB is full") + static final OptionValue HsailUseEdenAllocate = new OptionValue<>(false); + + @Option(help = "Estimate of number of bytes allocated by each HSAIL workitem, used to size TLABs") + static public final OptionValue HsailAllocBytesPerWorkitem = new OptionValue<>(64); + + // @formatter:on + } + + private static final boolean hsailUseEdenAllocate = HsailUseEdenAllocate.getValue(); + + @Snippet + public static Object allocateInstanceAtomic(@ConstantParameter int size, Word hub, Word prototypeMarkWord, @ConstantParameter boolean fillContents, @ConstantParameter String typeContext) { + Word thread = thread(); + boolean haveResult = false; + if (useTLAB()) { + Word top = atomicGetAndAddTlabTop(thread, size); + Word end = readTlabEnd(thread); + Word newTop = top.add(size); + if (probability(FAST_PATH_PROBABILITY, newTop.belowOrEqual(end))) { + // writeTlabTop(thread, newTop) was done by the atomicGetAndAdd + Object result = formatObject(hub, size, top, prototypeMarkWord, fillContents, true, false, true); + profileAllocation("instance", size, typeContext); + return piCast(verifyOop(result), StampFactory.forNodeIntrinsic()); + } else { + // only one overflower will be the first overflower, detectable because + // oldtop was still below end + if (top.belowOrEqual(end)) { + // hack alert: store the last good top before overflow into pf_top + // we will move it back into top later when back in the VM + writeTlabPfTop(thread, top); + } + // useless logic but see notes on deopt path below + haveResult = newTop.belowOrEqual(end); + } + } + if (hsailUseEdenAllocate) { + // originally: + // result = NewInstanceStubCall.call(hub); + + // we could not allocate from tlab, try allocating directly from eden + // false for no logging + Word memory = NewInstanceStub.edenAllocate(Word.unsigned(size), false); + if (memory.notEqual(0)) { + new_eden.inc(); + Object result = formatObject(hub, size, memory, prototypeMarkWord, fillContents, true, false, true); + profileAllocation("instance", size, typeContext); + return piCast(verifyOop(result), StampFactory.forNodeIntrinsic()); + } + } + // haveResult test here helps avoid dropping earlier stores were seen to be dropped without + // this. + if (!haveResult) { + DeoptimizeNode.deopt(DeoptimizationAction.None, DeoptimizationReason.RuntimeConstraint); + } + // will never get here but this keeps the compiler happy + return Word.zero().toObject(); + } + + @Snippet + public static Object allocateArrayAtomic(Word hub, int length, Word prototypeMarkWord, @ConstantParameter int headerSize, @ConstantParameter int log2ElementSize, + @ConstantParameter boolean fillContents, @ConstantParameter boolean maybeUnroll, @ConstantParameter String typeContext) { + if (!belowThan(length, MAX_ARRAY_FAST_PATH_ALLOCATION_LENGTH)) { + // This handles both negative array sizes and very large array sizes + DeoptimizeNode.deopt(DeoptimizationAction.None, DeoptimizationReason.RuntimeConstraint); + } + return allocateArrayAtomicImpl(hub, length, prototypeMarkWord, headerSize, log2ElementSize, fillContents, maybeUnroll, typeContext); + } + + private static Object allocateArrayAtomicImpl(Word hub, int length, Word prototypeMarkWord, int headerSize, int log2ElementSize, boolean fillContents, boolean maybeUnroll, String typeContext) { + int alignment = wordSize(); + int allocationSize = computeArrayAllocationSize(length, alignment, headerSize, log2ElementSize); + Word thread = thread(); + boolean haveResult = false; + if (useTLAB()) { + Word top = atomicGetAndAddTlabTop(thread, allocationSize); + Word end = readTlabEnd(thread); + Word newTop = top.add(allocationSize); + if (probability(FAST_PATH_PROBABILITY, newTop.belowOrEqual(end))) { + // writeTlabTop(thread, newTop) was done by the atomicGetAndAdd + newarray_loopInit.inc(); + // we are not in a stub so we can set useSnippetCounters to true + Object result = formatArray(hub, allocationSize, length, headerSize, top, prototypeMarkWord, fillContents, maybeUnroll, true); + profileAllocation("array", allocationSize, typeContext); + return piArrayCast(verifyOop(result), length, StampFactory.forNodeIntrinsic()); + } else { + // only one overflower will be the first overflower, detectable because + // oldtop was still below end + if (top.belowOrEqual(end)) { + // hack alert: store the last good top before overflow into pf_top + // we will move it back into top later when back in the VM + writeTlabPfTop(thread, top); + } + // useless logic but see notes on deopt path below + haveResult = newTop.belowOrEqual(end); + } + } + // we could not allocate from tlab, try allocating directly from eden + if (hsailUseEdenAllocate) { + // false for no logging + Word memory = NewInstanceStub.edenAllocate(Word.unsigned(allocationSize), false); + if (memory.notEqual(0)) { + newarray_eden.inc(); + // we are not in a stub so we can set useSnippetCounters to true + Object result = formatArray(hub, allocationSize, length, headerSize, memory, prototypeMarkWord, fillContents, maybeUnroll, true); + profileAllocation("array", allocationSize, typeContext); + return piArrayCast(verifyOop(result), length, StampFactory.forNodeIntrinsic()); + } + } + if (!haveResult) { + DeoptimizeNode.deopt(DeoptimizationAction.None, DeoptimizationReason.RuntimeConstraint); + } + // will never get here but this keeps the compiler happy + return Word.zero().toObject(); + } + + public static class Templates extends AbstractTemplates { + + private final SnippetInfo allocateInstance = snippet(HSAILNewObjectSnippets.class, "allocateInstanceAtomic"); + private final SnippetInfo allocateArray = snippet(HSAILNewObjectSnippets.class, "allocateArrayAtomic"); + + // private final SnippetInfo allocateArrayDynamic = snippet(NewObjectSnippets.class, + // "allocateArrayDynamic"); + // private final SnippetInfo newmultiarray = snippet(NewObjectSnippets.class, + // "newmultiarray"); + + public Templates(HotSpotProviders providers, TargetDescription target) { + super(providers, providers.getSnippetReflection(), target); + } + + /** + * Lowers a {@link NewInstanceNode}. + */ + public void lower(NewInstanceNode newInstanceNode, LoweringTool tool) { + StructuredGraph graph = newInstanceNode.graph(); + HotSpotResolvedObjectType type = (HotSpotResolvedObjectType) newInstanceNode.instanceClass(); + assert !type.isArray(); + ConstantNode hub = ConstantNode.forConstant(type.klass(), providers.getMetaAccess(), graph); + int size = instanceSize(type); + + Arguments args = new Arguments(allocateInstance, graph.getGuardsStage(), tool.getLoweringStage()); + args.addConst("size", size); + args.add("hub", hub); + args.add("prototypeMarkWord", type.prototypeMarkWord()); + args.addConst("fillContents", newInstanceNode.fillContents()); + args.addConst("typeContext", MetaUtil.toJavaName(type, false)); + + SnippetTemplate template = template(args); + Debug.log("Lowering allocateInstance in %s: node=%s, template=%s, arguments=%s", graph, newInstanceNode, template, args); + template.instantiate(providers.getMetaAccess(), newInstanceNode, DEFAULT_REPLACER, args); + } + + /** + * Lowers a {@link NewArrayNode}. + */ + public void lower(NewArrayNode newArrayNode, LoweringTool tool) { + StructuredGraph graph = newArrayNode.graph(); + ResolvedJavaType elementType = newArrayNode.elementType(); + HotSpotResolvedObjectType arrayType = (HotSpotResolvedObjectType) elementType.getArrayClass(); + Kind elementKind = elementType.getKind(); + ConstantNode hub = ConstantNode.forConstant(arrayType.klass(), providers.getMetaAccess(), graph); + final int headerSize = HotSpotGraalRuntime.getArrayBaseOffset(elementKind); + // lowerer extends HotSpotLoweringProvider so we can just use that + HotSpotLoweringProvider lowerer = (HotSpotLoweringProvider) providers.getLowerer(); + int log2ElementSize = CodeUtil.log2(lowerer.getScalingFactor(elementKind)); + + Arguments args = new Arguments(allocateArray, graph.getGuardsStage(), tool.getLoweringStage()); + args.add("hub", hub); + args.add("length", newArrayNode.length()); + args.add("prototypeMarkWord", arrayType.prototypeMarkWord()); + args.addConst("headerSize", headerSize); + args.addConst("log2ElementSize", log2ElementSize); + args.addConst("fillContents", newArrayNode.fillContents()); + args.addConst("maybeUnroll", newArrayNode.length().isConstant()); + args.addConst("typeContext", MetaUtil.toJavaName(arrayType, false)); + + SnippetTemplate template = template(args); + Debug.log("Lowering allocateArray in %s: node=%s, template=%s, arguments=%s", graph, newArrayNode, template, args); + template.instantiate(providers.getMetaAccess(), newArrayNode, DEFAULT_REPLACER, args); + } + + private static int instanceSize(HotSpotResolvedObjectType type) { + int size = type.instanceSize(); + assert (size % wordSize()) == 0; + assert size >= 0; + return size; + } + } + + private static final SnippetCounter.Group countersNew = SnippetCounters.getValue() ? new SnippetCounter.Group("NewInstance") : null; + private static final SnippetCounter new_eden = new SnippetCounter(countersNew, "eden", "used edenAllocate"); + + private static final SnippetCounter.Group countersNewArray = SnippetCounters.getValue() ? new SnippetCounter.Group("NewArray") : null; + private static final SnippetCounter newarray_loopInit = new SnippetCounter(countersNewArray, "tlabLoopInit", "TLAB alloc with zeroing in a loop"); + private static final SnippetCounter newarray_eden = new SnippetCounter(countersNewArray, "eden", "used edenAllocate"); +} diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.hotspot.ptx/src/com/oracle/graal/hotspot/ptx/PTXHotSpotBackend.java --- a/graal/com.oracle.graal.hotspot.ptx/src/com/oracle/graal/hotspot/ptx/PTXHotSpotBackend.java Fri Apr 25 16:21:07 2014 +0200 +++ b/graal/com.oracle.graal.hotspot.ptx/src/com/oracle/graal/hotspot/ptx/PTXHotSpotBackend.java Mon Apr 28 11:18:15 2014 +0200 @@ -36,11 +36,11 @@ import com.oracle.graal.api.meta.*; import com.oracle.graal.asm.*; import com.oracle.graal.asm.ptx.*; -import com.oracle.graal.compiler.gen.*; +import com.oracle.graal.compiler.common.*; +import com.oracle.graal.compiler.common.cfg.*; import com.oracle.graal.debug.*; import com.oracle.graal.debug.Debug.Scope; import com.oracle.graal.gpu.*; -import com.oracle.graal.graph.*; import com.oracle.graal.hotspot.*; import com.oracle.graal.hotspot.meta.*; import com.oracle.graal.lir.*; @@ -49,10 +49,12 @@ import com.oracle.graal.lir.LIRInstruction.ValueProcedure; import com.oracle.graal.lir.StandardOp.LabelOp; import com.oracle.graal.lir.asm.*; +import com.oracle.graal.lir.gen.*; import com.oracle.graal.lir.ptx.*; +import com.oracle.graal.lir.ptx.PTXControlFlow.PTXPredicatedLIRInstruction; import com.oracle.graal.lir.ptx.PTXMemOp.LoadReturnAddrOp; import com.oracle.graal.nodes.*; -import com.oracle.graal.nodes.cfg.*; +import com.oracle.graal.nodes.spi.*; import com.oracle.graal.phases.*; import com.oracle.graal.phases.common.*; import com.oracle.graal.phases.tiers.*; @@ -339,7 +341,7 @@ Assembler masm = createAssembler(frameMap); PTXFrameContext frameContext = new PTXFrameContext(); CompilationResultBuilder crb = factory.createBuilder(getCodeCache(), getForeignCalls(), frameMap, masm, frameContext, compilationResult); - crb.setFrameSize(0); + crb.setTotalFrameSize(0); return crb; } @@ -354,12 +356,12 @@ } @Override - public LIRGenerator newLIRGenerator(CallingConvention cc, LIRGenerationResult lirGenRes) { + public LIRGeneratorTool newLIRGenerator(CallingConvention cc, LIRGenerationResult lirGenRes) { return new PTXHotSpotLIRGenerator(getProviders(), getRuntime().getConfig(), cc, lirGenRes); } @Override - public NodeLIRBuilder newNodeLIRGenerator(StructuredGraph graph, LIRGenerator lirGen) { + public NodeLIRBuilderTool newNodeLIRBuilder(StructuredGraph graph, LIRGeneratorTool lirGen) { return new PTXHotSpotNodeLIRBuilder(graph, lirGen); } @@ -409,12 +411,20 @@ assert codeCacheOwner != null : lir + " is not associated with a method"; RegisterAnalysis registerAnalysis = new RegisterAnalysis(); + // Assume no predicate registers are used + int maxPredRegNum = -1; for (AbstractBlock b : lir.codeEmittingOrder()) { for (LIRInstruction op : lir.getLIRforBlock(b)) { if (op instanceof LabelOp) { // Don't consider this as a definition } else { + if (op instanceof PTXPredicatedLIRInstruction) { + // Update maximum predicate register number if op uses a larger number + int opPredRegNum = ((PTXPredicatedLIRInstruction) op).getPredRegNum(); + maxPredRegNum = (opPredRegNum > maxPredRegNum) ? opPredRegNum : maxPredRegNum; + } + // Record registers used in the kernel registerAnalysis.op = op; op.forEachTemp(registerAnalysis); op.forEachOutput(registerAnalysis); @@ -422,13 +432,13 @@ } } + // Emit register declarations Assembler asm = crb.asm; registerAnalysis.emitDeclarations(asm); // emit predicate register declaration - int maxPredRegNum = lir.numVariables(); - if (maxPredRegNum > 0) { - asm.emitString(".reg .pred %p<" + maxPredRegNum + ">;"); + if (maxPredRegNum > -1) { + asm.emitString(".reg .pred %p<" + ++maxPredRegNum + ">;"); } } diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.hotspot.ptx/src/com/oracle/graal/hotspot/ptx/PTXHotSpotForeignCallsProvider.java --- a/graal/com.oracle.graal.hotspot.ptx/src/com/oracle/graal/hotspot/ptx/PTXHotSpotForeignCallsProvider.java Fri Apr 25 16:21:07 2014 +0200 +++ b/graal/com.oracle.graal.hotspot.ptx/src/com/oracle/graal/hotspot/ptx/PTXHotSpotForeignCallsProvider.java Mon Apr 28 11:18:15 2014 +0200 @@ -24,7 +24,7 @@ import com.oracle.graal.api.code.*; import com.oracle.graal.api.meta.*; -import com.oracle.graal.graph.*; +import com.oracle.graal.compiler.common.*; import com.oracle.graal.hotspot.meta.*; public class PTXHotSpotForeignCallsProvider implements HotSpotForeignCallsProvider { diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.hotspot.ptx/src/com/oracle/graal/hotspot/ptx/PTXHotSpotLIRGenerator.java --- a/graal/com.oracle.graal.hotspot.ptx/src/com/oracle/graal/hotspot/ptx/PTXHotSpotLIRGenerator.java Fri Apr 25 16:21:07 2014 +0200 +++ b/graal/com.oracle.graal.hotspot.ptx/src/com/oracle/graal/hotspot/ptx/PTXHotSpotLIRGenerator.java Mon Apr 28 11:18:15 2014 +0200 @@ -25,12 +25,13 @@ import com.oracle.graal.api.code.*; import com.oracle.graal.api.meta.*; -import com.oracle.graal.compiler.gen.*; +import com.oracle.graal.compiler.common.*; import com.oracle.graal.compiler.ptx.*; -import com.oracle.graal.graph.*; import com.oracle.graal.hotspot.*; import com.oracle.graal.hotspot.HotSpotVMConfig.CompressEncoding; import com.oracle.graal.hotspot.meta.*; +import com.oracle.graal.lir.StandardOp.SaveRegistersOp; +import com.oracle.graal.lir.gen.*; /** * LIR generator specialized for PTX HotSpot. @@ -70,4 +71,32 @@ // TODO throw GraalInternalError.unimplemented(); } + + public void emitLeaveCurrentStackFrame() { + throw GraalInternalError.unimplemented(); + } + + public void emitLeaveDeoptimizedStackFrame(Value frameSize, Value initialInfo) { + throw GraalInternalError.unimplemented(); + } + + public void emitEnterUnpackFramesStackFrame(Value framePc, Value senderSp, Value senderFp) { + throw GraalInternalError.unimplemented(); + } + + public void emitLeaveUnpackFramesStackFrame() { + throw GraalInternalError.unimplemented(); + } + + public SaveRegistersOp emitSaveAllRegisters() { + throw GraalInternalError.unimplemented(); + } + + public void emitPushInterpreterFrame(Value frameSize, Value framePc, Value senderSp, Value initialInfo) { + throw GraalInternalError.unimplemented(); + } + + public Value emitUncommonTrapCall(Value trapRequest, SaveRegistersOp saveRegisterOp) { + throw GraalInternalError.unimplemented(); + } } diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.hotspot.ptx/src/com/oracle/graal/hotspot/ptx/PTXHotSpotLoweringProvider.java --- a/graal/com.oracle.graal.hotspot.ptx/src/com/oracle/graal/hotspot/ptx/PTXHotSpotLoweringProvider.java Fri Apr 25 16:21:07 2014 +0200 +++ b/graal/com.oracle.graal.hotspot.ptx/src/com/oracle/graal/hotspot/ptx/PTXHotSpotLoweringProvider.java Mon Apr 28 11:18:15 2014 +0200 @@ -22,6 +22,7 @@ */ package com.oracle.graal.hotspot.ptx; +import com.oracle.graal.compiler.common.*; import com.oracle.graal.graph.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.calc.*; diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.hotspot.ptx/src/com/oracle/graal/hotspot/ptx/PTXHotSpotNodeLIRBuilder.java --- a/graal/com.oracle.graal.hotspot.ptx/src/com/oracle/graal/hotspot/ptx/PTXHotSpotNodeLIRBuilder.java Fri Apr 25 16:21:07 2014 +0200 +++ b/graal/com.oracle.graal.hotspot.ptx/src/com/oracle/graal/hotspot/ptx/PTXHotSpotNodeLIRBuilder.java Mon Apr 28 11:18:15 2014 +0200 @@ -23,11 +23,11 @@ package com.oracle.graal.hotspot.ptx; -import com.oracle.graal.compiler.gen.*; +import com.oracle.graal.compiler.common.*; import com.oracle.graal.compiler.ptx.*; -import com.oracle.graal.graph.*; import com.oracle.graal.hotspot.*; import com.oracle.graal.hotspot.nodes.*; +import com.oracle.graal.lir.gen.*; import com.oracle.graal.nodes.*; /** @@ -35,7 +35,7 @@ */ public class PTXHotSpotNodeLIRBuilder extends PTXNodeLIRBuilder implements HotSpotNodeLIRBuilder { - protected PTXHotSpotNodeLIRBuilder(StructuredGraph graph, LIRGenerator lirGen) { + protected PTXHotSpotNodeLIRBuilder(StructuredGraph graph, LIRGeneratorTool lirGen) { super(graph, lirGen); } diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.hotspot.ptx/src/com/oracle/graal/hotspot/ptx/PTXHotSpotRegisterConfig.java --- a/graal/com.oracle.graal.hotspot.ptx/src/com/oracle/graal/hotspot/ptx/PTXHotSpotRegisterConfig.java Fri Apr 25 16:21:07 2014 +0200 +++ b/graal/com.oracle.graal.hotspot.ptx/src/com/oracle/graal/hotspot/ptx/PTXHotSpotRegisterConfig.java Mon Apr 28 11:18:15 2014 +0200 @@ -29,7 +29,7 @@ import com.oracle.graal.api.code.*; import com.oracle.graal.api.code.CallingConvention.Type; import com.oracle.graal.api.meta.*; -import com.oracle.graal.graph.*; +import com.oracle.graal.compiler.common.*; import com.oracle.graal.lir.*; public class PTXHotSpotRegisterConfig implements RegisterConfig { diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.hotspot.ptx/src/com/oracle/graal/hotspot/ptx/PTXWrapperBuilder.java --- a/graal/com.oracle.graal.hotspot.ptx/src/com/oracle/graal/hotspot/ptx/PTXWrapperBuilder.java Fri Apr 25 16:21:07 2014 +0200 +++ b/graal/com.oracle.graal.hotspot.ptx/src/com/oracle/graal/hotspot/ptx/PTXWrapperBuilder.java Mon Apr 28 11:18:15 2014 +0200 @@ -31,13 +31,12 @@ import static com.oracle.graal.hotspot.ptx.PTXWrapperBuilder.LaunchArg.*; import static com.oracle.graal.hotspot.replacements.HotSpotReplacementsUtil.*; import static com.oracle.graal.nodes.ConstantNode.*; -import static java.lang.reflect.Modifier.*; - import java.util.*; import com.oracle.graal.api.meta.*; +import com.oracle.graal.compiler.common.*; +import com.oracle.graal.compiler.common.type.*; import com.oracle.graal.debug.*; -import com.oracle.graal.graph.*; import com.oracle.graal.hotspot.meta.*; import com.oracle.graal.hotspot.nodes.*; import com.oracle.graal.java.*; @@ -47,7 +46,6 @@ import com.oracle.graal.nodes.calc.*; import com.oracle.graal.nodes.extended.*; import com.oracle.graal.nodes.java.*; -import com.oracle.graal.nodes.type.*; import com.oracle.graal.replacements.*; import com.oracle.graal.replacements.nodes.*; import com.oracle.graal.word.*; @@ -61,8 +59,8 @@ *

  • PINNED: a buffer into which the address of pinned objects is saved.
  • *
  • OBJECT_OFFSETS: the offsets of the object values in PARAMS.
  • *
- * - * + * + * * The PARAMS buffer is the {@code CU_LAUNCH_PARAM_BUFFER_POINTER} buffer passed in the * {@code extra} argument to the {@code cuLaunchKernel} function. This buffer contains the * parameters to the call. The buffer is word aligned and each parameter is aligned in the buffer @@ -74,13 +72,13 @@ * The object pointers in PARAMS are specified by OBJECT_OFFSETS. *

* As a concrete example, for a kernel whose Java method signature is: - * + * *

  *     static int kernel(int p1, short p2, Object p3, long p4)
  * 
- * + * * the graph created is shown below as psuedo-code: - * + * *
  *     int kernel_wrapper(int p1, short p2, oop p3, long p4) {
  *         address kernelAddr = kernel.start;
@@ -121,7 +119,7 @@
     /**
      * The size of the buffer holding the kernel parameters and the extra word for storing the
      * pointer to device memory for the return value.
-     * 
+     *
      * @see LaunchArg#ParametersAndReturnValueBufferSize
      */
     int bufSize;
@@ -152,7 +150,7 @@
 
     /**
      * Creates the graph implementing the CPU to GPU transition.
-     * 
+     *
      * @param method a method that has been compiled to GPU binary code
      * @param kernel the installed GPU binary for {@code method}
      * @see PTXWrapperBuilder
@@ -163,7 +161,7 @@
         int intSize = Integer.SIZE / Byte.SIZE;
         Kind wordKind = providers.getCodeCache().getTarget().wordKind;
         Signature sig = method.getSignature();
-        boolean isStatic = isStatic(method.getModifiers());
+        boolean isStatic = method.isStatic();
         int sigCount = sig.getParameterCount(false);
         javaParameters = new ParameterNode[(!isStatic ? 1 : 0) + sigCount];
         javaParameterOffsetsInKernelParametersBuffer = new int[javaParameters.length];
@@ -300,7 +298,7 @@
 
     /**
      * Computes offset and size of space in PARAMS for a Java parameter.
-     * 
+     *
      * @param kind the kind of the parameter
      * @param javaParametersIndex the index of the Java parameter
      */
diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCDeoptimizationStub.java
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCDeoptimizationStub.java	Mon Apr 28 11:18:15 2014 +0200
@@ -0,0 +1,48 @@
+/*
+ * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.graal.hotspot.sparc;
+
+import static com.oracle.graal.sparc.SPARC.*;
+
+import com.oracle.graal.api.code.*;
+import com.oracle.graal.hotspot.*;
+import com.oracle.graal.hotspot.meta.*;
+import com.oracle.graal.hotspot.stubs.*;
+
+final class SPARCDeoptimizationStub extends DeoptimizationStub {
+
+    private RegisterConfig registerConfig;
+
+    public SPARCDeoptimizationStub(HotSpotProviders providers, TargetDescription target, HotSpotForeignCallLinkage linkage) {
+        super(providers, target, linkage);
+        // This is basically the maximum we can spare. All other G and O register are used.
+        Register[] allocatable = new Register[]{g1, g3, g4, g5, o0, o1, o2, o3, o4};
+        registerConfig = new SPARCHotSpotRegisterConfig(target, allocatable);
+    }
+
+    @Override
+    public RegisterConfig getRegisterConfig() {
+        return registerConfig;
+    }
+
+}
diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCDeoptimizeOp.java
--- a/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCDeoptimizeOp.java	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCDeoptimizeOp.java	Mon Apr 28 11:18:15 2014 +0200
@@ -49,6 +49,6 @@
         // [Deopt Handler Code]
         // 0xffffffff749bb60c: call 0xffffffff748da540 ; {runtime_call}
         // 0xffffffff749bb610: nop
-        SPARCCall.directCall(crb, masm, crb.foreignCalls.lookupForeignCall(UNCOMMON_TRAP), null, false, info);
+        SPARCCall.directCall(crb, masm, crb.foreignCalls.lookupForeignCall(UNCOMMON_TRAP_HANDLER), null, false, info);
     }
 }
diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotBackend.java
--- a/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotBackend.java	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotBackend.java	Mon Apr 28 11:18:15 2014 +0200
@@ -24,10 +24,8 @@
 
 import static com.oracle.graal.api.code.CallingConvention.Type.*;
 import static com.oracle.graal.api.code.ValueUtil.*;
-import static com.oracle.graal.phases.GraalOptions.*;
+import static com.oracle.graal.compiler.common.GraalOptions.*;
 import static com.oracle.graal.sparc.SPARC.*;
-import static java.lang.reflect.Modifier.*;
-
 import java.util.*;
 
 import sun.misc.*;
@@ -45,8 +43,7 @@
 import com.oracle.graal.asm.sparc.SPARCMacroAssembler.Nop;
 import com.oracle.graal.asm.sparc.SPARCMacroAssembler.RestoreWindow;
 import com.oracle.graal.asm.sparc.SPARCMacroAssembler.Setx;
-import com.oracle.graal.compiler.gen.*;
-import com.oracle.graal.graph.*;
+import com.oracle.graal.compiler.common.*;
 import com.oracle.graal.hotspot.*;
 import com.oracle.graal.hotspot.meta.HotSpotCodeCacheProvider.MarkId;
 import com.oracle.graal.hotspot.meta.*;
@@ -54,8 +51,10 @@
 import com.oracle.graal.lir.*;
 import com.oracle.graal.lir.StandardOp.SaveRegistersOp;
 import com.oracle.graal.lir.asm.*;
+import com.oracle.graal.lir.gen.*;
 import com.oracle.graal.lir.sparc.*;
 import com.oracle.graal.nodes.*;
+import com.oracle.graal.nodes.spi.*;
 
 /**
  * HotSpot SPARC specific backend.
@@ -79,12 +78,17 @@
     }
 
     @Override
-    public LIRGenerator newLIRGenerator(CallingConvention cc, LIRGenerationResult lirGenRes) {
+    public LIRGeneratorTool newLIRGenerator(CallingConvention cc, LIRGenerationResult lirGenRes) {
         return new SPARCHotSpotLIRGenerator(getProviders(), getRuntime().getConfig(), cc, lirGenRes);
     }
 
     @Override
-    public NodeLIRBuilder newNodeLIRGenerator(StructuredGraph graph, LIRGenerator lirGen) {
+    public LIRGenerationResult newLIRGenerationResult(LIR lir, FrameMap frameMap, Object stub) {
+        return new SPARCHotSpotLIRGenerationResult(lir, frameMap, stub);
+    }
+
+    @Override
+    public NodeLIRBuilderTool newNodeLIRBuilder(StructuredGraph graph, LIRGeneratorTool lirGen) {
         return new SPARCHotSpotNodeLIRBuilder(graph, lirGen);
     }
 
@@ -174,7 +178,7 @@
         // On SPARC we always use stack frames.
         HotSpotFrameContext frameContext = new HotSpotFrameContext(stub != null);
         CompilationResultBuilder crb = factory.createBuilder(getProviders().getCodeCache(), getProviders().getForeignCalls(), frameMap, masm, frameContext, compilationResult);
-        crb.setFrameSize(frameMap.frameSize());
+        crb.setTotalFrameSize(frameMap.totalFrameSize());
         StackSlot deoptimizationRescueSlot = gen.getDeoptimizationRescueSlot();
         if (deoptimizationRescueSlot != null && stub == null) {
             crb.compilationResult.setCustomStackAreaOffset(frameMap.offsetForStackSlot(deoptimizationRescueSlot));
@@ -191,17 +195,12 @@
     }
 
     @Override
-    public LIRGenerationResult newLIRGenerationResult(LIR lir, FrameMap frameMap, Object stub) {
-        return new LIRGenerationResultBase(lir, frameMap);
-    }
-
-    @Override
     public void emitCode(CompilationResultBuilder crb, LIR lir, ResolvedJavaMethod installedCodeOwner) {
         SPARCMacroAssembler masm = (SPARCMacroAssembler) crb.asm;
         FrameMap frameMap = crb.frameMap;
         RegisterConfig regConfig = frameMap.registerConfig;
         HotSpotVMConfig config = getRuntime().getConfig();
-        Label unverifiedStub = installedCodeOwner == null || isStatic(installedCodeOwner.getModifiers()) ? null : new Label();
+        Label unverifiedStub = installedCodeOwner == null || installedCodeOwner.isStatic() ? null : new Label();
 
         // Emit the prefix
 
diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotCRuntimeCallPrologueOp.java
--- a/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotCRuntimeCallPrologueOp.java	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotCRuntimeCallPrologueOp.java	Mon Apr 28 11:18:15 2014 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 2014, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -48,9 +48,8 @@
 
     @Override
     public void emitCode(CompilationResultBuilder crb, SPARCMacroAssembler masm) {
-
         // Save last Java frame.
-        new Add(stackPointer, new SPARCAddress(stackPointer, 0).getDisplacement(), g4).emit(masm);
+        new Add(stackPointer, STACK_BIAS, g4).emit(masm);
         new Stx(g4, new SPARCAddress(thread, threadLastJavaSpOffset)).emit(masm);
 
         // Save the thread register when calling out to the runtime.
diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotDeoptimizeCallerOp.java
--- a/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotDeoptimizeCallerOp.java	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotDeoptimizeCallerOp.java	Mon Apr 28 11:18:15 2014 +0200
@@ -47,7 +47,7 @@
         // HotSpotFrameContext frameContext = backend.new HotSpotFrameContext(isStub);
         // frameContext.enter(crb);
         Register scratch = g3;
-        SPARCCall.indirectJmp(crb, masm, scratch, crb.foreignCalls.lookupForeignCall(UNCOMMON_TRAP));
+        SPARCCall.indirectJmp(crb, masm, scratch, crb.foreignCalls.lookupForeignCall(UNCOMMON_TRAP_HANDLER));
 
         // frameContext.leave(crb);
     }
diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotEnterUnpackFramesStackFrameOp.java
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotEnterUnpackFramesStackFrameOp.java	Mon Apr 28 11:18:15 2014 +0200
@@ -0,0 +1,96 @@
+/*
+ * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.graal.hotspot.sparc;
+
+import static com.oracle.graal.sparc.SPARC.*;
+import static com.oracle.graal.api.code.ValueUtil.*;
+import static com.oracle.graal.asm.sparc.SPARCMacroAssembler.*;
+import static com.oracle.graal.lir.LIRInstruction.OperandFlag.*;
+
+import com.oracle.graal.api.code.*;
+import com.oracle.graal.api.meta.*;
+import com.oracle.graal.asm.sparc.*;
+import com.oracle.graal.hotspot.stubs.*;
+import com.oracle.graal.lir.*;
+import com.oracle.graal.lir.sparc.*;
+import com.oracle.graal.lir.asm.*;
+
+/**
+ * Emits code that enters a stack frame which is tailored to call the C++ method
+ * {@link DeoptimizationStub#UNPACK_FRAMES Deoptimization::unpack_frames}.
+ */
+@Opcode("ENTER_UNPACK_FRAMES_STACK_FRAME")
+final class SPARCHotSpotEnterUnpackFramesStackFrameOp extends SPARCLIRInstruction {
+
+    private final Register thread;
+    private final int threadLastJavaSpOffset;
+    private final int threadLastJavaPcOffset;
+    @Alive(REG) AllocatableValue framePc;
+    @Alive(REG) AllocatableValue senderSp;
+    @Temp(REG) AllocatableValue scratch;
+
+    SPARCHotSpotEnterUnpackFramesStackFrameOp(Register thread, int threadLastJavaSpOffset, int threadLastJavaPcOffset, AllocatableValue framePc, AllocatableValue senderSp, AllocatableValue scratch) {
+        this.thread = thread;
+        this.threadLastJavaSpOffset = threadLastJavaSpOffset;
+        this.threadLastJavaPcOffset = threadLastJavaPcOffset;
+        this.framePc = framePc;
+        this.senderSp = senderSp;
+        this.scratch = scratch;
+    }
+
+    @Override
+    public void emitCode(CompilationResultBuilder crb, SPARCMacroAssembler masm) {
+        final int totalFrameSize = crb.frameMap.totalFrameSize();
+        Register framePcRegister = asRegister(framePc);
+        Register senderSpRegister = asRegister(senderSp);
+        Register scratchRegister = asRegister(scratch);
+
+        // Save final sender SP to O5_savedSP.
+        new Mov(senderSpRegister, o5).emit(masm);
+
+        // Load final frame PC.
+        new Mov(framePcRegister, o7).emit(masm);
+
+        // Allocate a full sized frame.
+        new Save(sp, -totalFrameSize, sp).emit(masm);
+
+        new Mov(i0, o0).emit(masm);
+        new Mov(i1, o1).emit(masm);
+        new Mov(i2, o2).emit(masm);
+        new Mov(i3, o3).emit(masm);
+        new Mov(i4, o4).emit(masm);
+
+        // Set up last Java values.
+        new Add(sp, STACK_BIAS, scratchRegister).emit(masm);
+        new Stx(scratchRegister, new SPARCAddress(thread, threadLastJavaSpOffset)).emit(masm);
+
+        // Clear last Java PC.
+        new Stx(g0, new SPARCAddress(thread, threadLastJavaPcOffset)).emit(masm);
+
+        /*
+         * Safe thread register manually since we are not using LEAF_SP for {@link
+         * DeoptimizationStub#UNPACK_FRAMES}.
+         */
+        new Mov(thread, l7).emit(masm);
+    }
+}
diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotForeignCallsProvider.java
--- a/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotForeignCallsProvider.java	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotForeignCallsProvider.java	Mon Apr 28 11:18:15 2014 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 2014, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -46,7 +46,8 @@
 
     @Override
     public void initialize(HotSpotProviders providers, HotSpotVMConfig config) {
-        Kind word = providers.getCodeCache().getTarget().wordKind;
+        TargetDescription target = providers.getCodeCache().getTarget();
+        Kind word = target.wordKind;
 
         // The calling convention for the exception handler stub is (only?) defined in
         // TemplateInterpreterGenerator::generate_throw_exception()
@@ -60,6 +61,8 @@
         register(new HotSpotForeignCallLinkage(EXCEPTION_HANDLER, 0L, PRESERVES_REGISTERS, LEAF_NOFP, outgoingExceptionCc, incomingExceptionCc, NOT_REEXECUTABLE, ANY_LOCATION));
         register(new HotSpotForeignCallLinkage(EXCEPTION_HANDLER_IN_CALLER, JUMP_ADDRESS, PRESERVES_REGISTERS, LEAF_NOFP, outgoingExceptionCc, incomingExceptionCc, NOT_REEXECUTABLE, ANY_LOCATION));
 
+        link(new SPARCDeoptimizationStub(providers, target, registerStubCall(UNCOMMON_TRAP_HANDLER, REEXECUTABLE, LEAF, NO_LOCATIONS)));
+
         super.initialize(providers, config);
     }
 
diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotLIRGenerationResult.java
--- a/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotLIRGenerationResult.java	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotLIRGenerationResult.java	Mon Apr 28 11:18:15 2014 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2014, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -22,14 +22,49 @@
  */
 package com.oracle.graal.hotspot.sparc;
 
+import java.util.*;
+
 import com.oracle.graal.api.code.*;
-import com.oracle.graal.compiler.gen.*;
 import com.oracle.graal.hotspot.stubs.*;
+import com.oracle.graal.lir.*;
+import com.oracle.graal.lir.StandardOp.*;
+import com.oracle.graal.lir.gen.*;
+
+public class SPARCHotSpotLIRGenerationResult extends LIRGenerationResultBase {
+
+    /**
+     * The slot reserved for storing the original return address when a frame is marked for
+     * deoptimization. The return address slot in the callee is overwritten with the address of a
+     * deoptimization stub.
+     */
+    private StackSlot deoptimizationRescueSlot;
+    private final Object stub;
 
-public interface SPARCHotSpotLIRGenerationResult extends LIRGenerationResult {
+    /**
+     * Map from debug infos that need to be updated with callee save information to the operations
+     * that provide the information.
+     */
+    private Map calleeSaveInfo = new HashMap<>();
+
+    public SPARCHotSpotLIRGenerationResult(LIR lir, FrameMap frameMap, Object stub) {
+        super(lir, frameMap);
+        this.stub = stub;
+    }
 
-    StackSlot getDeoptimizationRescueSlot();
+    StackSlot getDeoptimizationRescueSlot() {
+        return deoptimizationRescueSlot;
+    }
+
+    public final void setDeoptimizationRescueSlot(StackSlot deoptimizationRescueSlot) {
+        this.deoptimizationRescueSlot = deoptimizationRescueSlot;
+    }
 
-    Stub getStub();
+    Stub getStub() {
+        return (Stub) stub;
+    }
+
+    Map getCalleeSaveInfo() {
+        return calleeSaveInfo;
+    }
 
 }
diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotLIRGenerator.java
--- a/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotLIRGenerator.java	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotLIRGenerator.java	Mon Apr 28 11:18:15 2014 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 2014, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -24,27 +24,30 @@
 
 import static com.oracle.graal.api.code.ValueUtil.*;
 import static com.oracle.graal.hotspot.HotSpotGraalRuntime.*;
+import static com.oracle.graal.hotspot.nodes.UncommonTrapCallNode.*;
+import static com.oracle.graal.sparc.SPARC.*;
 
 import com.oracle.graal.api.code.*;
 import com.oracle.graal.api.meta.*;
-import com.oracle.graal.compiler.gen.*;
+import com.oracle.graal.compiler.common.*;
 import com.oracle.graal.compiler.sparc.*;
-import com.oracle.graal.graph.*;
 import com.oracle.graal.hotspot.*;
 import com.oracle.graal.hotspot.HotSpotVMConfig.CompressEncoding;
 import com.oracle.graal.hotspot.meta.*;
 import com.oracle.graal.hotspot.stubs.*;
 import com.oracle.graal.lir.*;
+import com.oracle.graal.lir.StandardOp.SaveRegistersOp;
+import com.oracle.graal.lir.gen.*;
 import com.oracle.graal.lir.sparc.*;
 import com.oracle.graal.lir.sparc.SPARCMove.LoadOp;
 import com.oracle.graal.lir.sparc.SPARCMove.StoreConstantOp;
 import com.oracle.graal.lir.sparc.SPARCMove.StoreOp;
-import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.extended.*;
 
 public class SPARCHotSpotLIRGenerator extends SPARCLIRGenerator implements HotSpotLIRGenerator {
 
     final HotSpotVMConfig config;
+    private HotSpotLockStack lockStack;
 
     public SPARCHotSpotLIRGenerator(HotSpotProviders providers, HotSpotVMConfig config, CallingConvention cc, LIRGenerationResult lirGenRes) {
         super(providers, cc, lirGenRes);
@@ -65,11 +68,21 @@
 
     @Override
     public StackSlot getLockSlot(int lockDepth) {
-        return ((HotSpotDebugInfoBuilder) getDebugInfoBuilder()).lockStack().makeLockSlot(lockDepth);
+        return getLockStack().makeLockSlot(lockDepth);
+    }
+
+    private HotSpotLockStack getLockStack() {
+        assert lockStack != null;
+        return lockStack;
+    }
+
+    protected void setLockStack(HotSpotLockStack lockStack) {
+        assert this.lockStack == null;
+        this.lockStack = lockStack;
     }
 
     @Override
-    protected boolean needOnlyOopMaps() {
+    public boolean needOnlyOopMaps() {
         // Stubs only need oop maps
         return getStub() != null;
     }
@@ -79,12 +92,13 @@
     }
 
     @Override
-    public Variable emitForeignCall(ForeignCallLinkage linkage, DeoptimizingNode info, Value... args) {
+    public Variable emitForeignCall(ForeignCallLinkage linkage, LIRFrameState state, Value... args) {
         HotSpotForeignCallLinkage hotspotLinkage = (HotSpotForeignCallLinkage) linkage;
         Variable result;
-        DeoptimizingNode deoptInfo = null;
+        // TODO (je) check if this can be removed
+        LIRFrameState deoptInfo = null;
         if (hotspotLinkage.canDeoptimize()) {
-            deoptInfo = info;
+            deoptInfo = state;
             assert deoptInfo != null || getStub() != null;
         }
 
@@ -141,9 +155,9 @@
     }
 
     @Override
-    public void emitDeoptimize(Value actionAndReason, Value speculation, DeoptimizingNode deopting) {
+    public void emitDeoptimize(Value actionAndReason, Value speculation, LIRFrameState state) {
         moveDeoptValuesToThread(actionAndReason, speculation);
-        append(new SPARCDeoptimizeOp(state(deopting)));
+        append(new SPARCDeoptimizeOp(state));
     }
 
     @Override
@@ -157,14 +171,10 @@
     }
 
     @Override
-    public Variable emitLoad(PlatformKind kind, Value address, Access access) {
+    public Variable emitLoad(PlatformKind kind, Value address, LIRFrameState state) {
         SPARCAddressValue loadAddress = asAddressValue(address);
         Variable result = newVariable(kind);
-        LIRFrameState state = null;
-        if (access instanceof DeoptimizingNode) {
-            state = state((DeoptimizingNode) access);
-        }
-        if (isCompressCandidate(access)) {
+        if (isCompressCandidate(null)) {
             if (config.useCompressedOops && kind == Kind.Object) {
                 // append(new LoadCompressedPointer(kind, result, loadAddress, access != null ?
                 // state(access) :
@@ -187,19 +197,15 @@
     }
 
     @Override
-    public void emitStore(PlatformKind kind, Value address, Value inputVal, Access access) {
+    public void emitStore(PlatformKind kind, Value address, Value inputVal, LIRFrameState state) {
         SPARCAddressValue storeAddress = asAddressValue(address);
-        LIRFrameState state = null;
-        if (access instanceof DeoptimizingNode) {
-            state = state((DeoptimizingNode) access);
-        }
         if (isConstant(inputVal)) {
             Constant c = asConstant(inputVal);
-            if (canStoreConstant(c, isCompressCandidate(access))) {
+            if (canStoreConstant(c, isCompressCandidate(null))) {
                 if (inputVal.getKind() == Kind.Object) {
-                    append(new StoreConstantOp((Kind) kind, storeAddress, c, state, config.useCompressedOops && isCompressCandidate(access)));
+                    append(new StoreConstantOp((Kind) kind, storeAddress, c, state, config.useCompressedOops && isCompressCandidate(null)));
                 } else if (inputVal.getKind() == Kind.Long) {
-                    append(new StoreConstantOp((Kind) kind, storeAddress, c, state, config.useCompressedClassPointers && isCompressCandidate(access)));
+                    append(new StoreConstantOp((Kind) kind, storeAddress, c, state, config.useCompressedClassPointers && isCompressCandidate(null)));
                 } else {
                     append(new StoreConstantOp((Kind) kind, storeAddress, c, state, false));
                 }
@@ -207,7 +213,7 @@
             }
         }
         Variable input = load(inputVal);
-        if (isCompressCandidate(access)) {
+        if (isCompressCandidate(null)) {
             if (config.useCompressedOops && kind == Kind.Object) {
                 // if (input.getKind() == Kind.Object) {
                 // Variable scratch = newVariable(Kind.Long);
@@ -234,7 +240,8 @@
     }
 
     public Value emitCompareAndSwap(Value address, Value expectedValue, Value newValue, Value trueValue, Value falseValue) {
-        throw new InternalError("NYI");
+        // TODO Auto-generated method stub
+        throw GraalInternalError.unimplemented();
     }
 
     @Override
@@ -258,4 +265,79 @@
         // TODO
         throw GraalInternalError.unimplemented();
     }
+
+    /**
+     * @param savedRegisters the registers saved by this operation which may be subject to pruning
+     * @param savedRegisterLocations the slots to which the registers are saved
+     * @param supportsRemove determines if registers can be pruned
+     */
+    protected SPARCSaveRegistersOp emitSaveRegisters(Register[] savedRegisters, StackSlot[] savedRegisterLocations, boolean supportsRemove) {
+        SPARCSaveRegistersOp save = new SPARCSaveRegistersOp(savedRegisters, savedRegisterLocations, supportsRemove);
+        append(save);
+        return save;
+    }
+
+    public SaveRegistersOp emitSaveAllRegisters() {
+        // We save all registers that were not saved by the save instruction.
+        // @formatter:off
+        Register[] savedRegisters = {
+                        // CPU
+                        g1, g3, g4, g5,
+                        // FPU
+                        f0,  f1,  f2,  f3,  f4,  f5,  f6,  f7,
+                        f8,  f9,  f10, f11, f12, f13, f14, f15,
+                        f16, f17, f18, f19, f20, f21, f22, f23,
+                        f24, f25, f26, f27, f28, f29, f30, f31
+        };
+        // @formatter:on
+        StackSlot[] savedRegisterLocations = new StackSlot[savedRegisters.length];
+        for (int i = 0; i < savedRegisters.length; i++) {
+            PlatformKind kind = target().arch.getLargestStorableKind(savedRegisters[i].getRegisterCategory());
+            assert kind != Kind.Illegal;
+            StackSlot spillSlot = getResult().getFrameMap().allocateSpillSlot(kind);
+            savedRegisterLocations[i] = spillSlot;
+        }
+        return emitSaveRegisters(savedRegisters, savedRegisterLocations, false);
+    }
+
+    public void emitLeaveCurrentStackFrame() {
+        append(new SPARCHotSpotLeaveCurrentStackFrameOp());
+    }
+
+    public void emitLeaveDeoptimizedStackFrame(Value frameSize, Value initialInfo) {
+        append(new SPARCHotSpotLeaveDeoptimizedStackFrameOp());
+    }
+
+    public void emitEnterUnpackFramesStackFrame(Value framePc, Value senderSp, Value senderFp) {
+        Register thread = getProviders().getRegisters().getThreadRegister();
+        Variable framePcVariable = load(framePc);
+        Variable senderSpVariable = load(senderSp);
+        Variable scratchVariable = newVariable(getHostWordKind());
+        append(new SPARCHotSpotEnterUnpackFramesStackFrameOp(thread, config.threadLastJavaSpOffset(), config.threadLastJavaPcOffset(), framePcVariable, senderSpVariable, scratchVariable));
+    }
+
+    public void emitLeaveUnpackFramesStackFrame() {
+        Register thread = getProviders().getRegisters().getThreadRegister();
+        append(new SPARCHotSpotLeaveUnpackFramesStackFrameOp(thread, config.threadLastJavaSpOffset(), config.threadLastJavaPcOffset(), config.threadJavaFrameAnchorFlagsOffset()));
+    }
+
+    public void emitPushInterpreterFrame(Value frameSize, Value framePc, Value senderSp, Value initialInfo) {
+        Variable frameSizeVariable = load(frameSize);
+        Variable framePcVariable = load(framePc);
+        Variable senderSpVariable = load(senderSp);
+        Variable initialInfoVariable = load(initialInfo);
+        append(new SPARCHotSpotPushInterpreterFrameOp(frameSizeVariable, framePcVariable, senderSpVariable, initialInfoVariable));
+    }
+
+    public Value emitUncommonTrapCall(Value trapRequest, SaveRegistersOp saveRegisterOp) {
+        ForeignCallLinkage linkage = getForeignCalls().lookupForeignCall(UNCOMMON_TRAP);
+
+        Register threadRegister = getProviders().getRegisters().getThreadRegister();
+        Register stackPointerRegister = getProviders().getRegisters().getStackPointerRegister();
+        append(new SPARCHotSpotCRuntimeCallPrologueOp(config.threadLastJavaSpOffset(), threadRegister, stackPointerRegister));
+        Variable result = super.emitForeignCall(linkage, null, threadRegister.asValue(Kind.Long), trapRequest);
+        append(new SPARCHotSpotCRuntimeCallEpilogueOp(config.threadLastJavaSpOffset(), config.threadLastJavaPcOffset(), config.threadJavaFrameAnchorFlagsOffset(), threadRegister));
+
+        return result;
+    }
 }
diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotLeaveCurrentStackFrameOp.java
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotLeaveCurrentStackFrameOp.java	Mon Apr 28 11:18:15 2014 +0200
@@ -0,0 +1,49 @@
+/*
+ * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.graal.hotspot.sparc;
+
+import static com.oracle.graal.sparc.SPARC.*;
+
+import com.oracle.graal.asm.sparc.*;
+import com.oracle.graal.asm.sparc.SPARCMacroAssembler.*;
+import com.oracle.graal.lir.*;
+import com.oracle.graal.lir.asm.*;
+
+/**
+ * Pops the current frame off the stack.
+ */
+@Opcode("LEAVE_CURRENT_STACK_FRAME")
+final class SPARCHotSpotLeaveCurrentStackFrameOp extends SPARCHotSpotEpilogueOp {
+
+    @Override
+    public void emitCode(CompilationResultBuilder crb, SPARCMacroAssembler masm) {
+        // Save O registers over restore.
+        new Mov(o0, i0).emit(masm);
+        new Mov(o1, i1).emit(masm);
+        new Mov(o2, i2).emit(masm);
+        new Mov(o3, i3).emit(masm);
+        new Mov(o4, i4).emit(masm);
+
+        leaveFrame(crb);
+    }
+}
diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotLeaveDeoptimizedStackFrameOp.java
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotLeaveDeoptimizedStackFrameOp.java	Mon Apr 28 11:18:15 2014 +0200
@@ -0,0 +1,49 @@
+/*
+ * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.graal.hotspot.sparc;
+
+import static com.oracle.graal.asm.sparc.SPARCMacroAssembler.*;
+import static com.oracle.graal.sparc.SPARC.*;
+
+import com.oracle.graal.asm.sparc.*;
+import com.oracle.graal.lir.*;
+import com.oracle.graal.lir.asm.*;
+
+/**
+ * Pops the current frame off the stack including the return address.
+ */
+@Opcode("LEAVE_DEOPTIMIZED_STACK_FRAME")
+final class SPARCHotSpotLeaveDeoptimizedStackFrameOp extends SPARCHotSpotEpilogueOp {
+
+    @Override
+    public void emitCode(CompilationResultBuilder crb, SPARCMacroAssembler masm) {
+        // Save O registers over restore.
+        new Mov(o0, i0).emit(masm);
+        new Mov(o1, i1).emit(masm);
+        new Mov(o2, i2).emit(masm);
+        new Mov(o3, i3).emit(masm);
+        new Mov(o4, i4).emit(masm);
+
+        new RestoreWindow().emit(masm);
+    }
+}
diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotLeaveUnpackFramesStackFrameOp.java
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotLeaveUnpackFramesStackFrameOp.java	Mon Apr 28 11:18:15 2014 +0200
@@ -0,0 +1,67 @@
+/*
+ * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.graal.hotspot.sparc;
+
+import static com.oracle.graal.asm.sparc.SPARCMacroAssembler.*;
+import static com.oracle.graal.sparc.SPARC.*;
+
+import com.oracle.graal.api.code.*;
+import com.oracle.graal.asm.sparc.*;
+import com.oracle.graal.hotspot.stubs.*;
+import com.oracle.graal.lir.*;
+import com.oracle.graal.lir.sparc.*;
+import com.oracle.graal.lir.asm.*;
+
+/**
+ * Emits code that leaves a stack frame which is tailored to call the C++ method
+ * {@link DeoptimizationStub#UNPACK_FRAMES Deoptimization::unpack_frames}.
+ */
+@Opcode("LEAVE_UNPACK_FRAMES_STACK_FRAME")
+final class SPARCHotSpotLeaveUnpackFramesStackFrameOp extends SPARCLIRInstruction {
+
+    private final Register thread;
+    private final int threadLastJavaSpOffset;
+    private final int threadLastJavaPcOffset;
+    private final int threadJavaFrameAnchorFlagsOffset;
+
+    SPARCHotSpotLeaveUnpackFramesStackFrameOp(Register thread, int threadLastJavaSpOffset, int threadLastJavaPcOffset, int threadJavaFrameAnchorFlagsOffset) {
+        this.thread = thread;
+        this.threadLastJavaSpOffset = threadLastJavaSpOffset;
+        this.threadLastJavaPcOffset = threadLastJavaPcOffset;
+        this.threadJavaFrameAnchorFlagsOffset = threadJavaFrameAnchorFlagsOffset;
+    }
+
+    @Override
+    public void emitCode(CompilationResultBuilder crb, SPARCMacroAssembler masm) {
+        /*
+         * Safe thread register manually since we are not using LEAF_SP for {@link
+         * DeoptimizationStub#UNPACK_FRAMES}.
+         */
+        new Mov(l7, thread).emit(masm);
+
+        // Clear last Java frame values.
+        new Stx(g0, new SPARCAddress(thread, threadLastJavaSpOffset)).emit(masm);
+        new Stx(g0, new SPARCAddress(thread, threadLastJavaPcOffset)).emit(masm);
+        new Stw(g0, new SPARCAddress(thread, threadJavaFrameAnchorFlagsOffset)).emit(masm);
+    }
+}
diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotNodeLIRBuilder.java
--- a/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotNodeLIRBuilder.java	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotNodeLIRBuilder.java	Mon Apr 28 11:18:15 2014 +0200
@@ -26,8 +26,6 @@
 import static com.oracle.graal.hotspot.HotSpotBackend.*;
 import static com.oracle.graal.sparc.SPARC.*;
 
-import java.lang.reflect.*;
-
 import com.oracle.graal.api.code.*;
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.compiler.gen.*;
@@ -37,6 +35,7 @@
 import com.oracle.graal.hotspot.meta.*;
 import com.oracle.graal.hotspot.nodes.*;
 import com.oracle.graal.lir.*;
+import com.oracle.graal.lir.gen.*;
 import com.oracle.graal.lir.sparc.*;
 import com.oracle.graal.lir.sparc.SPARCMove.CompareAndSwapOp;
 import com.oracle.graal.nodes.*;
@@ -44,8 +43,11 @@
 
 public class SPARCHotSpotNodeLIRBuilder extends SPARCNodeLIRBuilder implements HotSpotNodeLIRBuilder {
 
-    public SPARCHotSpotNodeLIRBuilder(StructuredGraph graph, LIRGenerator lirGen) {
+    public SPARCHotSpotNodeLIRBuilder(StructuredGraph graph, LIRGeneratorTool lirGen) {
         super(graph, lirGen);
+        assert gen instanceof SPARCHotSpotLIRGenerator;
+        assert getDebugInfoBuilder() instanceof HotSpotDebugInfoBuilder;
+        ((SPARCHotSpotLIRGenerator) gen).setLockStack(((HotSpotDebugInfoBuilder) getDebugInfoBuilder()).lockStack());
     }
 
     @Override
@@ -60,7 +62,7 @@
 
     @Override
     public void visitSafepointNode(SafepointNode i) {
-        LIRFrameState info = gen.state(i);
+        LIRFrameState info = state(i);
         append(new SPARCHotSpotSafepointOp(info, getGen().config, gen));
     }
 
@@ -100,9 +102,8 @@
         } else {
             assert invokeKind == InvokeKind.Static || invokeKind == InvokeKind.Special;
             HotSpotResolvedJavaMethod resolvedMethod = (HotSpotResolvedJavaMethod) callTarget.target();
-            assert !Modifier.isAbstract(resolvedMethod.getModifiers()) : "Cannot make direct call to abstract method.";
-            Constant metaspaceMethod = resolvedMethod.getMetaspaceMethodConstant();
-            append(new SPARCHotspotDirectStaticCallOp(callTarget.target(), result, parameters, temps, callState, invokeKind, metaspaceMethod));
+            assert !resolvedMethod.isAbstract() : "Cannot make direct call to abstract method.";
+            append(new SPARCHotspotDirectStaticCallOp(callTarget.target(), result, parameters, temps, callState, invokeKind));
         }
     }
 
diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotPushInterpreterFrameOp.java
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotPushInterpreterFrameOp.java	Mon Apr 28 11:18:15 2014 +0200
@@ -0,0 +1,78 @@
+/*
+ * Copyright (c) 2013, 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.graal.hotspot.sparc;
+
+import static com.oracle.graal.asm.sparc.SPARCMacroAssembler.*;
+import static com.oracle.graal.sparc.SPARC.*;
+import static com.oracle.graal.api.code.ValueUtil.*;
+import static com.oracle.graal.lir.LIRInstruction.OperandFlag.*;
+
+import com.oracle.graal.api.code.*;
+import com.oracle.graal.api.meta.*;
+import com.oracle.graal.asm.sparc.*;
+import com.oracle.graal.lir.*;
+import com.oracle.graal.lir.sparc.*;
+import com.oracle.graal.lir.asm.*;
+
+/**
+ * Pushes an interpreter frame to the stack.
+ */
+@Opcode("PUSH_INTERPRETER_FRAME")
+final class SPARCHotSpotPushInterpreterFrameOp extends SPARCLIRInstruction {
+
+    @Alive(REG) AllocatableValue frameSize;
+    @Alive(REG) AllocatableValue framePc;
+    @Alive(REG) AllocatableValue senderSp;
+    @Alive(REG) AllocatableValue initialInfo;
+
+    SPARCHotSpotPushInterpreterFrameOp(AllocatableValue frameSize, AllocatableValue framePc, AllocatableValue senderSp, AllocatableValue initialInfo) {
+        this.frameSize = frameSize;
+        this.framePc = framePc;
+        this.senderSp = senderSp;
+        this.initialInfo = initialInfo;
+    }
+
+    @Override
+    public void emitCode(CompilationResultBuilder crb, SPARCMacroAssembler masm) {
+        final Register frameSizeRegister = asRegister(frameSize);
+        final Register framePcRegister = asRegister(framePc);
+        final Register senderSpRegister = asRegister(senderSp);
+
+        // Save sender SP to O5_savedSP.
+        new Mov(senderSpRegister, o5).emit(masm);
+
+        new Neg(frameSizeRegister).emit(masm);
+        new Save(sp, frameSizeRegister, sp).emit(masm);
+
+        new Mov(i0, o0).emit(masm);
+        new Mov(i1, o1).emit(masm);
+        new Mov(i2, o2).emit(masm);
+        new Mov(i3, o3).emit(masm);
+        new Mov(i4, o4).emit(masm);
+
+        // NOTE: Don't touch I5 as it contains valuable saved SP!
+
+        // Move frame's new PC into i7
+        new Mov(framePcRegister, i7).emit(masm);
+    }
+}
diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotRegisterConfig.java
--- a/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotRegisterConfig.java	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotRegisterConfig.java	Mon Apr 28 11:18:15 2014 +0200
@@ -22,7 +22,7 @@
  */
 package com.oracle.graal.hotspot.sparc;
 
-import static com.oracle.graal.phases.GraalOptions.*;
+import static com.oracle.graal.compiler.common.GraalOptions.*;
 import static com.oracle.graal.sparc.SPARC.*;
 
 import java.util.*;
@@ -30,7 +30,7 @@
 import com.oracle.graal.api.code.*;
 import com.oracle.graal.api.code.CallingConvention.Type;
 import com.oracle.graal.api.meta.*;
-import com.oracle.graal.graph.*;
+import com.oracle.graal.compiler.common.*;
 import com.oracle.graal.hotspot.*;
 import com.oracle.graal.lir.*;
 import com.oracle.graal.sparc.*;
@@ -98,25 +98,27 @@
 
     private static Register[] initAllocatable(boolean reserveForHeapBase) {
         Register[] registers = null;
-        // @formatter:off
         if (reserveForHeapBase) {
-            registers = new Register[] {
+            // @formatter:off
+            registers = new Register[]{
                         // TODO this is not complete
                         o0, o1, o2, o3, o4, o5, /*o6,*/ o7,
                         l0, l1, l2, l3, l4, l5, l6, l7,
                         i0, i1, i2, i3, i4, i5, /*i6,*/ /*i7,*/
                         f0, f1, f2, f3, f4, f5, f6, f7
-                      };
+            };
+            // @formatter:on
         } else {
-            registers = new Register[] {
+            // @formatter:off
+            registers = new Register[]{
                         // TODO this is not complete
                         o0, o1, o2, o3, o4, o5, /*o6,*/ o7,
                         l0, l1, l2, l3, l4, l5, l6, l7,
                         i0, i1, i2, i3, i4, i5, /*i6,*/ /*i7,*/
                         f0, f1, f2, f3, f4, f5, f6, f7
-                      };
+            };
+            // @formatter:on
         }
-       // @formatter:on
 
         if (RegisterPressure.getValue() != null) {
             String[] names = RegisterPressure.getValue().split(",");
diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotSafepointOp.java
--- a/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotSafepointOp.java	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotSafepointOp.java	Mon Apr 28 11:18:15 2014 +0200
@@ -33,8 +33,10 @@
 import com.oracle.graal.hotspot.meta.HotSpotCodeCacheProvider.MarkId;
 import com.oracle.graal.lir.*;
 import com.oracle.graal.lir.asm.*;
+import com.oracle.graal.lir.gen.*;
 import com.oracle.graal.lir.sparc.*;
-import com.oracle.graal.nodes.spi.*;
+
+import edu.umd.cs.findbugs.annotations.*;
 
 /**
  * Emits a safepoint poll.
@@ -43,7 +45,7 @@
 public class SPARCHotSpotSafepointOp extends SPARCLIRInstruction {
 
     @State protected LIRFrameState state;
-    @Temp({OperandFlag.REG}) private AllocatableValue temp;
+    @SuppressFBWarnings(value = "BC_IMPOSSIBLE_CAST", justification = "changed by the register allocator") @Temp({OperandFlag.REG}) private AllocatableValue temp;
 
     private final HotSpotVMConfig config;
 
diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotspotDirectStaticCallOp.java
--- a/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotspotDirectStaticCallOp.java	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotspotDirectStaticCallOp.java	Mon Apr 28 11:18:15 2014 +0200
@@ -22,44 +22,32 @@
  */
 package com.oracle.graal.hotspot.sparc;
 
-import static com.oracle.graal.sparc.SPARC.*;
-
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.asm.sparc.*;
-import com.oracle.graal.asm.sparc.SPARCMacroAssembler.Setx;
-import com.oracle.graal.hotspot.*;
 import com.oracle.graal.hotspot.meta.HotSpotCodeCacheProvider.MarkId;
 import com.oracle.graal.lir.*;
 import com.oracle.graal.lir.asm.*;
 import com.oracle.graal.lir.sparc.SPARCCall.DirectCallOp;
-import com.oracle.graal.lir.sparc.*;
 import com.oracle.graal.nodes.java.MethodCallTargetNode.InvokeKind;
 
 /**
- * A direct call that complies with the conventions for such calls in HotSpot. In particular, for
- * calls using an inline cache, a MOVE instruction is emitted just prior to the aligned direct call.
+ * A direct call that complies with the conventions for such calls in HotSpot. It doesn't use an
+ * inline cache so it's just a patchable call site.
  */
 @Opcode("CALL_DIRECT")
 final class SPARCHotspotDirectStaticCallOp extends DirectCallOp {
 
-    private final Constant metaspaceMethod;
     private final InvokeKind invokeKind;
 
-    SPARCHotspotDirectStaticCallOp(ResolvedJavaMethod target, Value result, Value[] parameters, Value[] temps, LIRFrameState state, InvokeKind invokeKind, Constant metaspaceMethod) {
+    SPARCHotspotDirectStaticCallOp(ResolvedJavaMethod target, Value result, Value[] parameters, Value[] temps, LIRFrameState state, InvokeKind invokeKind) {
         super(target, result, parameters, temps, state);
         assert invokeKind == InvokeKind.Static || invokeKind == InvokeKind.Special;
-        this.metaspaceMethod = metaspaceMethod;
         this.invokeKind = invokeKind;
     }
 
     @Override
     public void emitCode(CompilationResultBuilder crb, SPARCMacroAssembler masm) {
-        // The mark for an invocation that uses an inline cache must be placed at the
-        // instruction that loads the Klass from the inline cache.
-        SPARCMove.move(crb, masm, g5.asValue(Kind.Long), metaspaceMethod);
         MarkId.recordMark(crb, invokeKind == InvokeKind.Static ? MarkId.INVOKESTATIC : MarkId.INVOKESPECIAL);
-        // SPARCMove.move(crb, masm, g3.asValue(Kind.Long), Constant.LONG_0);
-        new Setx(HotSpotGraalRuntime.runtime().getConfig().nonOopBits, g3, true).emit(masm);
         super.emitCode(crb, masm);
     }
 }
diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.hotspot.test/src/com/oracle/graal/hotspot/test/AheadOfTimeCompilationTest.java
--- a/graal/com.oracle.graal.hotspot.test/src/com/oracle/graal/hotspot/test/AheadOfTimeCompilationTest.java	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.hotspot.test/src/com/oracle/graal/hotspot/test/AheadOfTimeCompilationTest.java	Mon Apr 28 11:18:15 2014 +0200
@@ -24,8 +24,8 @@
 
 import static com.oracle.graal.api.code.CodeUtil.*;
 import static com.oracle.graal.compiler.GraalCompiler.*;
+import static com.oracle.graal.compiler.common.GraalOptions.*;
 import static com.oracle.graal.nodes.ConstantNode.*;
-import static com.oracle.graal.phases.GraalOptions.*;
 
 import org.junit.*;
 
diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.hotspot.test/src/com/oracle/graal/hotspot/test/CompileTheWorldTest.java
--- a/graal/com.oracle.graal.hotspot.test/src/com/oracle/graal/hotspot/test/CompileTheWorldTest.java	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.hotspot.test/src/com/oracle/graal/hotspot/test/CompileTheWorldTest.java	Mon Apr 28 11:18:15 2014 +0200
@@ -22,7 +22,7 @@
  */
 package com.oracle.graal.hotspot.test;
 
-import static com.oracle.graal.phases.GraalOptions.*;
+import static com.oracle.graal.compiler.common.GraalOptions.*;
 
 import org.junit.*;
 
diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.hotspot.test/src/com/oracle/graal/hotspot/test/CompressedOopTest.java
--- a/graal/com.oracle.graal.hotspot.test/src/com/oracle/graal/hotspot/test/CompressedOopTest.java	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.hotspot.test/src/com/oracle/graal/hotspot/test/CompressedOopTest.java	Mon Apr 28 11:18:15 2014 +0200
@@ -200,7 +200,7 @@
         while (j < objects.length) {
             if (!installedBenchmarkCode.isValid()) {
                 // This can get invalidated due to lack of MDO update
-                installedBenchmarkCode = getInstalledCode("queueTest");
+                installedBenchmarkCode = getInstalledCode("queueTest", Object.class, Object.class);
             }
             installedBenchmarkCode.executeVarargs(q, objects[j]);
             j++;
diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.hotspot.test/src/com/oracle/graal/hotspot/test/HotSpotMonitorValueTest.java
--- a/graal/com.oracle.graal.hotspot.test/src/com/oracle/graal/hotspot/test/HotSpotMonitorValueTest.java	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.hotspot.test/src/com/oracle/graal/hotspot/test/HotSpotMonitorValueTest.java	Mon Apr 28 11:18:15 2014 +0200
@@ -33,8 +33,8 @@
 import com.oracle.graal.api.code.CompilationResult.Call;
 import com.oracle.graal.api.code.CompilationResult.Infopoint;
 import com.oracle.graal.api.meta.*;
+import com.oracle.graal.compiler.common.*;
 import com.oracle.graal.compiler.test.*;
-import com.oracle.graal.graph.*;
 import com.oracle.graal.hotspot.meta.*;
 
 public class HotSpotMonitorValueTest extends GraalCompilerTest {
diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.hotspot.test/src/com/oracle/graal/hotspot/test/HotSpotResolvedJavaFieldTest.java
--- a/graal/com.oracle.graal.hotspot.test/src/com/oracle/graal/hotspot/test/HotSpotResolvedJavaFieldTest.java	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.hotspot.test/src/com/oracle/graal/hotspot/test/HotSpotResolvedJavaFieldTest.java	Mon Apr 28 11:18:15 2014 +0200
@@ -24,7 +24,6 @@
 
 import static com.oracle.graal.hotspot.HotSpotGraalRuntime.*;
 import static com.oracle.graal.hotspot.meta.HotSpotResolvedObjectType.*;
-import static java.lang.reflect.Modifier.*;
 
 import java.lang.reflect.*;
 
@@ -79,7 +78,7 @@
     public void testIsInObject() {
         for (Field f : String.class.getDeclaredFields()) {
             HotSpotResolvedJavaField rf = (HotSpotResolvedJavaField) runtime().getHostProviders().getMetaAccess().lookupJavaField(f);
-            Assert.assertEquals(rf.toString(), rf.isInObject("a string"), !isStatic(rf.getModifiers()));
+            Assert.assertEquals(rf.toString(), rf.isInObject("a string"), !rf.isStatic());
         }
     }
 }
diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.hotspot.test/src/com/oracle/graal/hotspot/test/WriteBarrierVerificationTest.java
--- a/graal/com.oracle.graal.hotspot.test/src/com/oracle/graal/hotspot/test/WriteBarrierVerificationTest.java	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.hotspot.test/src/com/oracle/graal/hotspot/test/WriteBarrierVerificationTest.java	Mon Apr 28 11:18:15 2014 +0200
@@ -685,7 +685,7 @@
                 }
 
                 @Override
-                protected Boolean afterSplit(AbstractBeginNode node, Boolean oldState) {
+                protected Boolean afterSplit(BeginNode node, Boolean oldState) {
                     return false;
                 }
             };
diff -r 3dde8d8c95b8 -r 40d0022115ee 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	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/CompilationTask.java	Mon Apr 28 11:18:15 2014 +0200
@@ -25,14 +25,13 @@
 import static com.oracle.graal.api.code.CallingConvention.Type.*;
 import static com.oracle.graal.api.code.CodeUtil.*;
 import static com.oracle.graal.compiler.GraalCompiler.*;
+import static com.oracle.graal.compiler.common.GraalOptions.*;
 import static com.oracle.graal.hotspot.bridge.VMToCompilerImpl.*;
 import static com.oracle.graal.nodes.StructuredGraph.*;
-import static com.oracle.graal.phases.GraalOptions.*;
 import static com.oracle.graal.phases.common.InliningUtil.*;
 
 import java.io.*;
 import java.lang.management.*;
-import java.lang.reflect.*;
 import java.util.*;
 import java.util.concurrent.*;
 import java.util.concurrent.atomic.*;
@@ -42,6 +41,7 @@
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.baseline.*;
 import com.oracle.graal.compiler.*;
+import com.oracle.graal.compiler.common.*;
 import com.oracle.graal.debug.*;
 import com.oracle.graal.debug.Debug.Scope;
 import com.oracle.graal.debug.internal.*;
@@ -312,7 +312,7 @@
             }
 
             try (TimerCloseable b = CodeInstallationTime.start()) {
-                installedCode = installMethod(result);
+                installedCode = (HotSpotInstalledCode) installMethod(result);
                 if (!isOSR) {
                     ProfilingInfo profile = method.getProfilingInfo();
                     profile.setCompilerIRSize(StructuredGraph.class, graph.getNodeCount());
@@ -363,7 +363,6 @@
      */
     private void printCompilation() {
         final boolean isOSR = entryBCI != StructuredGraph.INVOCATION_ENTRY_BCI;
-        final int mod = method.getModifiers();
         String compilerName = "";
         if (HotSpotCIPrintCompilerName.getValue()) {
             compilerName = "Graal:";
@@ -380,14 +379,14 @@
             compLevelString = "";
         }
         boolean hasExceptionHandlers = method.getExceptionHandlers().length > 0;
-        TTY.println(String.format("%s%7d %4d %c%c%c%c%c %s      %s %s(%d bytes)", compilerName, backend.getRuntime().compilerToVm.getTimeStamp(), id, isOSR ? '%' : ' ',
-                        Modifier.isSynchronized(mod) ? 's' : ' ', hasExceptionHandlers ? '!' : ' ', blocking ? 'b' : ' ', Modifier.isNative(mod) ? 'n' : ' ', compLevelString,
-                        MetaUtil.format("%H::%n(%p)", method), isOSR ? "@ " + entryBCI + " " : "", method.getCodeSize()));
+        TTY.println(String.format("%s%7d %4d %c%c%c%c%c %s      %s %s(%d bytes)", compilerName, backend.getRuntime().compilerToVm.getTimeStamp(), id, isOSR ? '%' : ' ', method.isSynchronized() ? 's'
+                        : ' ', hasExceptionHandlers ? '!' : ' ', blocking ? 'b' : ' ', method.isNative() ? 'n' : ' ', compLevelString, MetaUtil.format("%H::%n(%p)", method), isOSR ? "@ " + entryBCI +
+                        " " : "", method.getCodeSize()));
     }
 
-    private HotSpotInstalledCode installMethod(final CompilationResult compResult) {
+    private InstalledCode installMethod(final CompilationResult compResult) {
         final HotSpotCodeCacheProvider codeCache = backend.getProviders().getCodeCache();
-        HotSpotInstalledCode installedCode = null;
+        InstalledCode installedCode = null;
         try (Scope s = Debug.scope("CodeInstall", new DebugDumpScope(String.valueOf(id), true), codeCache, method)) {
             installedCode = codeCache.installMethod(method, compResult);
         } catch (Throwable e) {
diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/CompileTheWorld.java
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/CompileTheWorld.java	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/CompileTheWorld.java	Mon Apr 28 11:18:15 2014 +0200
@@ -22,9 +22,9 @@
  */
 package com.oracle.graal.hotspot;
 
+import static com.oracle.graal.compiler.common.GraalOptions.*;
 import static com.oracle.graal.hotspot.HotSpotGraalRuntime.*;
 import static com.oracle.graal.nodes.StructuredGraph.*;
-import static com.oracle.graal.phases.GraalOptions.*;
 
 import java.io.*;
 import java.lang.reflect.*;
@@ -35,8 +35,8 @@
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.api.meta.ProfilingInfo.TriState;
 import com.oracle.graal.bytecode.*;
+import com.oracle.graal.compiler.common.*;
 import com.oracle.graal.debug.*;
-import com.oracle.graal.graph.*;
 import com.oracle.graal.hotspot.HotSpotOptions.OptionConsumer;
 import com.oracle.graal.hotspot.meta.*;
 import com.oracle.graal.options.*;
@@ -311,7 +311,7 @@
         }
 
         println();
-        TTY.println("CompileTheWorld : Done (%d classes, %d methods, %d ms)", classFileCounter, compiledMethodsCounter, compileTime);
+        println("CompileTheWorld : Done (%d classes, %d methods, %d ms)", classFileCounter, compiledMethodsCounter, compileTime);
     }
 
     class CTWCompilationTask extends CompilationTask {
diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotBackend.java
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotBackend.java	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotBackend.java	Mon Apr 28 11:18:15 2014 +0200
@@ -27,6 +27,7 @@
 import com.oracle.graal.api.code.*;
 import com.oracle.graal.api.code.stack.*;
 import com.oracle.graal.api.meta.*;
+import com.oracle.graal.compiler.common.cfg.*;
 import com.oracle.graal.compiler.target.*;
 import com.oracle.graal.hotspot.meta.*;
 import com.oracle.graal.hotspot.stubs.*;
@@ -35,7 +36,6 @@
 import com.oracle.graal.lir.StandardOp.LabelOp;
 import com.oracle.graal.lir.StandardOp.SaveRegistersOp;
 import com.oracle.graal.nodes.*;
-import com.oracle.graal.nodes.cfg.*;
 import com.oracle.graal.phases.tiers.*;
 import com.oracle.graal.word.*;
 
@@ -45,9 +45,9 @@
 public abstract class HotSpotBackend extends Backend {
 
     /**
-     * Descriptor for SharedRuntime::deopt_blob()->uncommon_trap().
+     * Descriptor for {@link DeoptimizationStub}.
      */
-    public static final ForeignCallDescriptor UNCOMMON_TRAP = new ForeignCallDescriptor("deoptimize", void.class);
+    public static final ForeignCallDescriptor UNCOMMON_TRAP_HANDLER = new ForeignCallDescriptor("uncommonTrapHandler", void.class);
 
     /**
      * Descriptor for {@link ExceptionHandlerStub}. This stub is called by the
diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotCompiledRuntimeStub.java
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotCompiledRuntimeStub.java	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotCompiledRuntimeStub.java	Mon Apr 28 11:18:15 2014 +0200
@@ -22,11 +22,14 @@
  */
 package com.oracle.graal.hotspot;
 
+import static com.oracle.graal.hotspot.HotSpotBackend.*;
+
 import com.oracle.graal.api.code.*;
 import com.oracle.graal.api.code.CompilationResult.Call;
 import com.oracle.graal.api.code.CompilationResult.DataPatch;
 import com.oracle.graal.api.code.CompilationResult.Infopoint;
 import com.oracle.graal.hotspot.data.*;
+import com.oracle.graal.hotspot.meta.*;
 import com.oracle.graal.hotspot.stubs.*;
 
 /**
@@ -40,8 +43,8 @@
 
     public HotSpotCompiledRuntimeStub(TargetDescription target, Stub stub, CompilationResult compResult) {
         super(target, compResult);
+        this.stubName = stub.toString();
         assert checkStubInvariants(compResult);
-        this.stubName = stub.toString();
     }
 
     /**
@@ -50,6 +53,15 @@
     private boolean checkStubInvariants(CompilationResult compResult) {
         assert compResult.getExceptionHandlers().isEmpty();
         for (DataPatch data : compResult.getDataReferences()) {
+            if (data.data instanceof MetaspaceData) {
+                MetaspaceData meta = (MetaspaceData) data.data;
+                if (meta.annotation instanceof HotSpotResolvedObjectType && ((HotSpotResolvedObjectType) meta.annotation).getName().equals("[I")) {
+                    // special handling for NewArrayStub
+                    // embedding the type '[I' is safe, since it is never unloaded
+                    continue;
+                }
+            }
+
             assert !(data.data instanceof PatchedData) : this + " cannot have embedded object or metadata constant: " + data.data;
         }
         for (Infopoint infopoint : compResult.getInfopoints()) {
@@ -57,8 +69,13 @@
             Call call = (Call) infopoint;
             assert call.target instanceof HotSpotForeignCallLinkage : this + " cannot have non runtime call: " + call.target;
             HotSpotForeignCallLinkage linkage = (HotSpotForeignCallLinkage) call.target;
-            assert !linkage.isCompiledStub() : this + " cannot call compiled stub " + linkage;
+            assert !linkage.isCompiledStub() || linkage.getDescriptor() == UNCOMMON_TRAP_HANDLER : this + " cannot call compiled stub " + linkage;
         }
         return true;
     }
+
+    @Override
+    public String toString() {
+        return stubName != null ? stubName : super.toString();
+    }
 }
diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotDebugInfoBuilder.java
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotDebugInfoBuilder.java	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotDebugInfoBuilder.java	Mon Apr 28 11:18:15 2014 +0200
@@ -64,4 +64,10 @@
     protected LIRFrameState newLIRFrameState(LabelRef exceptionEdge, BytecodeFrame frame, VirtualObject[] virtualObjectsArray) {
         return new HotSpotLIRFrameState(frame, virtualObjectsArray, exceptionEdge);
     }
+
+    @Override
+    protected BytecodeFrame computeFrameForState(FrameState state) {
+        assert state.bci >= 0 || state.bci == BytecodeFrame.BEFORE_BCI;
+        return super.computeFrameForState(state);
+    }
 }
diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotGraalRuntime.java
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotGraalRuntime.java	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotGraalRuntime.java	Mon Apr 28 11:18:15 2014 +0200
@@ -22,9 +22,9 @@
  */
 package com.oracle.graal.hotspot;
 
-import static com.oracle.graal.graph.UnsafeAccess.*;
+import static com.oracle.graal.compiler.common.GraalOptions.*;
+import static com.oracle.graal.compiler.common.UnsafeAccess.*;
 import static com.oracle.graal.hotspot.HotSpotGraalRuntime.Options.*;
-import static com.oracle.graal.phases.GraalOptions.*;
 
 import java.lang.reflect.*;
 import java.util.*;
@@ -37,8 +37,8 @@
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.api.replacements.*;
 import com.oracle.graal.api.runtime.*;
+import com.oracle.graal.compiler.common.*;
 import com.oracle.graal.compiler.target.*;
-import com.oracle.graal.graph.*;
 import com.oracle.graal.hotspot.bridge.*;
 import com.oracle.graal.hotspot.logging.*;
 import com.oracle.graal.hotspot.meta.*;
@@ -445,10 +445,12 @@
         }
     }
 
-    public Iterable getStackTrace(final ResolvedJavaMethod initialMethod, final ResolvedJavaMethod matchingMethod) {
+    public Iterable getStackTrace(ResolvedJavaMethod[] initialMethods, ResolvedJavaMethod[] matchingMethods, int initialSkip) {
+        final long[] initialMetaMethods = toMeta(initialMethods);
+        final long[] matchingMetaMethods = toMeta(matchingMethods);
         class StackFrameIterator implements Iterator {
 
-            private HotSpotStackFrameReference current = compilerToVm.getNextStackFrame(null, (HotSpotResolvedJavaMethod) initialMethod);
+            private HotSpotStackFrameReference current = compilerToVm.getNextStackFrame(null, initialMetaMethods, initialSkip);
             // we don't want to read ahead if hasNext isn't called
             private boolean advanced = true;
 
@@ -465,7 +467,7 @@
 
             private void update() {
                 if (!advanced) {
-                    current = compilerToVm.getNextStackFrame(current, (HotSpotResolvedJavaMethod) matchingMethod);
+                    current = compilerToVm.getNextStackFrame(current, matchingMetaMethods, 0);
                     advanced = true;
                 }
             }
@@ -476,4 +478,16 @@
             }
         };
     }
+
+    private static long[] toMeta(ResolvedJavaMethod[] methods) {
+        if (methods == null) {
+            return null;
+        } else {
+            long[] result = new long[methods.length];
+            for (int i = 0; i < result.length; i++) {
+                result[i] = ((HotSpotResolvedJavaMethod) methods[i]).getMetaspaceMethod();
+            }
+            return result;
+        }
+    }
 }
diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotHostBackend.java
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotHostBackend.java	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotHostBackend.java	Mon Apr 28 11:18:15 2014 +0200
@@ -22,7 +22,7 @@
  */
 package com.oracle.graal.hotspot;
 
-import static com.oracle.graal.phases.GraalOptions.*;
+import static com.oracle.graal.compiler.common.GraalOptions.*;
 
 import java.util.*;
 
@@ -63,7 +63,7 @@
             try (Scope s = Debug.scope("RegisterReplacements", new DebugDumpScope("RegisterReplacements"))) {
                 ServiceLoader sl = ServiceLoader.loadInstalled(ReplacementsProvider.class);
                 for (ReplacementsProvider replacementsProvider : sl) {
-                    replacementsProvider.registerReplacements(providers.getMetaAccess(), lowerer, replacements, providers.getCodeCache().getTarget());
+                    replacementsProvider.registerReplacements(providers.getMetaAccess(), lowerer, providers.getSnippetReflection(), replacements, providers.getCodeCache().getTarget());
                 }
                 if (BootstrapReplacements.getValue()) {
                     for (ResolvedJavaMethod method : replacements.getAllReplacements()) {
diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotLIRGenerator.java
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotLIRGenerator.java	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotLIRGenerator.java	Mon Apr 28 11:18:15 2014 +0200
@@ -24,16 +24,16 @@
 
 import com.oracle.graal.api.code.*;
 import com.oracle.graal.api.meta.*;
-import com.oracle.graal.compiler.gen.*;
 import com.oracle.graal.hotspot.HotSpotVMConfig.CompressEncoding;
 import com.oracle.graal.hotspot.meta.*;
-import com.oracle.graal.nodes.spi.*;
+import com.oracle.graal.lir.StandardOp.SaveRegistersOp;
+import com.oracle.graal.lir.gen.*;
 
 /**
  * This interface defines the contract a HotSpot backend LIR generator needs to fulfill in addition
- * to abstract methods from {@link LIRGenerator} and {@link NodeLIRBuilderTool}.
+ * to abstract methods from {@link LIRGenerator} and {@link LIRGeneratorTool}.
  */
-public interface HotSpotLIRGenerator {
+public interface HotSpotLIRGenerator extends LIRGeneratorTool {
 
     /**
      * Emits an operation to make a tail call.
@@ -43,8 +43,22 @@
      */
     void emitTailcall(Value[] args, Value address);
 
+    void emitLeaveCurrentStackFrame();
+
+    void emitLeaveDeoptimizedStackFrame(Value frameSize, Value initialInfo);
+
+    void emitEnterUnpackFramesStackFrame(Value framePc, Value senderSp, Value senderFp);
+
+    void emitLeaveUnpackFramesStackFrame();
+
+    SaveRegistersOp emitSaveAllRegisters();
+
     void emitDeoptimizeCaller(DeoptimizationAction action, DeoptimizationReason reason);
 
+    void emitPushInterpreterFrame(Value frameSize, Value framePc, Value senderSp, Value initialInfo);
+
+    Value emitUncommonTrapCall(Value trapRequest, SaveRegistersOp saveRegisterOp);
+
     /**
      * Gets a stack slot for a lock at a given lock nesting depth.
      */
diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotNodeLIRBuilder.java
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotNodeLIRBuilder.java	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotNodeLIRBuilder.java	Mon Apr 28 11:18:15 2014 +0200
@@ -22,8 +22,8 @@
  */
 package com.oracle.graal.hotspot;
 
-import com.oracle.graal.compiler.gen.*;
 import com.oracle.graal.hotspot.nodes.*;
+import com.oracle.graal.lir.gen.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.spi.*;
 
diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotOptions.java
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotOptions.java	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotOptions.java	Mon Apr 28 11:18:15 2014 +0200
@@ -33,8 +33,8 @@
 import java.nio.file.*;
 import java.util.*;
 
+import com.oracle.graal.compiler.common.*;
 import com.oracle.graal.debug.*;
-import com.oracle.graal.graph.*;
 import com.oracle.graal.hotspot.logging.*;
 import com.oracle.graal.options.*;
 import com.oracle.graal.phases.common.*;
diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotReplacementsImpl.java
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotReplacementsImpl.java	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotReplacementsImpl.java	Mon Apr 28 11:18:15 2014 +0200
@@ -27,10 +27,10 @@
 import com.oracle.graal.api.code.*;
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.api.replacements.*;
+import com.oracle.graal.compiler.common.*;
 import com.oracle.graal.hotspot.meta.*;
 import com.oracle.graal.hotspot.replacements.*;
 import com.oracle.graal.nodes.*;
-import com.oracle.graal.phases.*;
 import com.oracle.graal.phases.util.*;
 import com.oracle.graal.replacements.*;
 
diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotSymbol.java
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotSymbol.java	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotSymbol.java	Mon Apr 28 11:18:15 2014 +0200
@@ -22,12 +22,12 @@
  */
 package com.oracle.graal.hotspot;
 
-import static com.oracle.graal.graph.UnsafeAccess.*;
+import static com.oracle.graal.compiler.common.UnsafeAccess.*;
 import static com.oracle.graal.hotspot.HotSpotGraalRuntime.*;
 
 import java.io.*;
 
-import com.oracle.graal.graph.*;
+import com.oracle.graal.compiler.common.*;
 
 /**
  * Represents a metaspace {@code Symbol}.
diff -r 3dde8d8c95b8 -r 40d0022115ee 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	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotVMConfig.java	Mon Apr 28 11:18:15 2014 +0200
@@ -22,12 +22,12 @@
  */
 package com.oracle.graal.hotspot;
 
-import static com.oracle.graal.graph.UnsafeAccess.*;
+import static com.oracle.graal.compiler.common.UnsafeAccess.*;
 
 import java.lang.reflect.*;
 import java.util.*;
 
-import com.oracle.graal.graph.*;
+import com.oracle.graal.compiler.common.*;
 import com.oracle.graal.hotspot.bridge.*;
 import com.oracle.graal.hotspot.meta.*;
 
@@ -794,6 +794,7 @@
     // offsets, ...
     @HotSpotVMFlag(name = "StackShadowPages") @Stable public int stackShadowPages;
     @HotSpotVMFlag(name = "UseStackBanging") @Stable public boolean useStackBanging;
+    @HotSpotVMConstant(name = "STACK_BIAS") @Stable public int stackBias;
 
     @HotSpotVMField(name = "oopDesc::_mark", type = "markOop", get = HotSpotVMField.Type.OFFSET) @Stable public int markOffset;
     @HotSpotVMField(name = "oopDesc::_metadata._klass", type = "Klass*", get = HotSpotVMField.Type.OFFSET) @Stable public int hubOffset;
@@ -962,7 +963,10 @@
         return javaThreadAnchorOffset + javaFrameAnchorFlagsOffset;
     }
 
+    // These are only valid on AMD64.
     @HotSpotVMConstant(name = "frame::arg_reg_save_area_bytes", archs = {"amd64"}) @Stable public int runtimeCallStackSize;
+    @HotSpotVMConstant(name = "frame::interpreter_frame_sender_sp_offset", archs = {"amd64"}) @Stable public int frameInterpreterFrameSenderSpOffset;
+    @HotSpotVMConstant(name = "frame::interpreter_frame_last_sp_offset", archs = {"amd64"}) @Stable public int frameInterpreterFrameLastSpOffset;
 
     @HotSpotVMField(name = "PtrQueue::_active", type = "bool", get = HotSpotVMField.Type.OFFSET) @Stable public int ptrQueueActiveOffset;
     @HotSpotVMField(name = "PtrQueue::_buf", type = "void**", get = HotSpotVMField.Type.OFFSET) @Stable public int ptrQueueBufferOffset;
@@ -1010,16 +1014,19 @@
     @HotSpotVMField(name = "ThreadShadow::_pending_failed_speculation", type = "oop", get = HotSpotVMField.Type.OFFSET) @Stable public int pendingFailedSpeculationOffset;
 
     @HotSpotVMFlag(name = "UseHSAILDeoptimization") @Stable public boolean useHSAILDeoptimization;
+    @HotSpotVMFlag(name = "UseHSAILSafepoints") @Stable public boolean useHSAILSafepoints;
 
     /**
      * Offsets of Hsail deoptimization fields (defined in gpu_hsail.hpp). Used to propagate
      * exceptions from Hsail back to C++ runtime.
      */
+    @HotSpotVMField(name = "Hsail::HSAILDeoptimizationInfo::_notice_safepoints", type = "jint*", get = HotSpotVMField.Type.OFFSET) @Stable public int hsailNoticeSafepointsOffset;
     @HotSpotVMField(name = "Hsail::HSAILDeoptimizationInfo::_deopt_save_states[0]", type = "Hsail::HSAILKernelDeoptimization", get = HotSpotVMField.Type.OFFSET) @Stable public int hsailSaveStatesOffset0;
     @HotSpotVMField(name = "Hsail::HSAILDeoptimizationInfo::_deopt_save_states[1]", type = "Hsail::HSAILKernelDeoptimization", get = HotSpotVMField.Type.OFFSET) @Stable public int hsailSaveStatesOffset1;
-    @HotSpotVMField(name = "Hsail::HSAILDeoptimizationInfo::_deopt_occurred", type = "jint", get = HotSpotVMField.Type.OFFSET) @Stable public int hsailDeoptOffset;
+    @HotSpotVMField(name = "Hsail::HSAILDeoptimizationInfo::_deopt_occurred", type = "jint", get = HotSpotVMField.Type.OFFSET) @Stable public int hsailDeoptOccurredOffset;
     @HotSpotVMField(name = "Hsail::HSAILDeoptimizationInfo::_never_ran_array", type = "jboolean *", get = HotSpotVMField.Type.OFFSET) @Stable public int hsailNeverRanArrayOffset;
     @HotSpotVMField(name = "Hsail::HSAILDeoptimizationInfo::_deopt_next_index", type = "jint", get = HotSpotVMField.Type.OFFSET) @Stable public int hsailDeoptNextIndexOffset;
+    @HotSpotVMField(name = "Hsail::HSAILDeoptimizationInfo::_donor_threads", type = "JavaThread**", get = HotSpotVMField.Type.OFFSET) @Stable public int hsailDonorThreadsOffset;
 
     @HotSpotVMField(name = "Hsail::HSAILKernelDeoptimization::_workitemid", type = "jint", get = HotSpotVMField.Type.OFFSET) @Stable public int hsailDeoptimizationWorkItem;
     @HotSpotVMField(name = "Hsail::HSAILKernelDeoptimization::_actionAndReason", type = "jint", get = HotSpotVMField.Type.OFFSET) @Stable public int hsailDeoptimizationReason;
@@ -1055,6 +1062,7 @@
     @HotSpotVMConstant(name = "Method::_force_inline") @Stable public int methodFlagsForceInline;
     @HotSpotVMConstant(name = "Method::_dont_inline") @Stable public int methodFlagsDontInline;
     @HotSpotVMConstant(name = "Method::_hidden") @Stable public int methodFlagsHidden;
+    @HotSpotVMConstant(name = "Method::nonvirtual_vtable_index") @Stable public int nonvirtualVtableIndex;
 
     @HotSpotVMConstant(name = "JVM_ACC_MONITOR_MATCH") @Stable public int jvmAccMonitorMatch;
     @HotSpotVMConstant(name = "JVM_ACC_HAS_MONITOR_BYTECODES") @Stable public int jvmAccHasMonitorBytecodes;
@@ -1245,6 +1253,7 @@
     @HotSpotVMField(name = "ThreadLocalAllocBuffer::_start", type = "HeapWord*", get = HotSpotVMField.Type.OFFSET) @Stable private int threadLocalAllocBufferStartOffset;
     @HotSpotVMField(name = "ThreadLocalAllocBuffer::_end", type = "HeapWord*", get = HotSpotVMField.Type.OFFSET) @Stable private int threadLocalAllocBufferEndOffset;
     @HotSpotVMField(name = "ThreadLocalAllocBuffer::_top", type = "HeapWord*", get = HotSpotVMField.Type.OFFSET) @Stable private int threadLocalAllocBufferTopOffset;
+    @HotSpotVMField(name = "ThreadLocalAllocBuffer::_pf_top", type = "HeapWord*", get = HotSpotVMField.Type.OFFSET) @Stable private int threadLocalAllocBufferPfTopOffset;
     @HotSpotVMField(name = "ThreadLocalAllocBuffer::_slow_allocations", type = "unsigned", get = HotSpotVMField.Type.OFFSET) @Stable private int threadLocalAllocBufferSlowAllocationsOffset;
     @HotSpotVMField(name = "ThreadLocalAllocBuffer::_fast_refill_waste", type = "unsigned", get = HotSpotVMField.Type.OFFSET) @Stable private int threadLocalAllocBufferFastRefillWasteOffset;
     @HotSpotVMField(name = "ThreadLocalAllocBuffer::_number_of_refills", type = "unsigned", get = HotSpotVMField.Type.OFFSET) @Stable private int threadLocalAllocBufferNumberOfRefillsOffset;
@@ -1283,6 +1292,10 @@
         return threadTlabOffset + threadLocalAllocBufferTopOffset;
     }
 
+    public int threadTlabPfTopOffset() {
+        return threadTlabOffset + threadLocalAllocBufferPfTopOffset;
+    }
+
     @HotSpotVMFlag(name = "TLABStats") @Stable public boolean tlabStats;
     @Stable public boolean inlineContiguousAllocationSupported;
 
@@ -1341,7 +1354,6 @@
     }
 
     @Stable public long handleDeoptStub;
-    @Stable public long uncommonTrapStub;
 
     @HotSpotVMField(name = "StubRoutines::_aescrypt_encryptBlock", type = "address", get = HotSpotVMField.Type.VALUE) @Stable public long aescryptEncryptBlockStub;
     @HotSpotVMField(name = "StubRoutines::_aescrypt_decryptBlock", type = "address", get = HotSpotVMField.Type.VALUE) @Stable public long aescryptDecryptBlockStub;
@@ -1411,6 +1423,10 @@
 
     @Stable public int graalCountersSize;
 
+    @Stable public long deoptimizationFetchUnrollInfo;
+    @Stable public long deoptimizationUncommonTrap;
+    @Stable public long deoptimizationUnpackFrames;
+
     @HotSpotVMConstant(name = "Deoptimization::Reason_none") @Stable public int deoptReasonNone;
     @HotSpotVMConstant(name = "Deoptimization::Reason_null_check") @Stable public int deoptReasonNullCheck;
     @HotSpotVMConstant(name = "Deoptimization::Reason_range_check") @Stable public int deoptReasonRangeCheck;
@@ -1441,6 +1457,19 @@
     @HotSpotVMConstant(name = "Deoptimization::_reason_shift") @Stable public int deoptimizationReasonShift;
     @HotSpotVMConstant(name = "Deoptimization::_debug_id_shift") @Stable public int deoptimizationDebugIdShift;
 
+    @HotSpotVMConstant(name = "Deoptimization::Unpack_deopt") @Stable public int deoptimizationUnpackDeopt;
+    @HotSpotVMConstant(name = "Deoptimization::Unpack_exception") @Stable public int deoptimizationUnpackException;
+    @HotSpotVMConstant(name = "Deoptimization::Unpack_uncommon_trap") @Stable public int deoptimizationUnpackUncommonTrap;
+    @HotSpotVMConstant(name = "Deoptimization::Unpack_reexecute") @Stable public int deoptimizationUnpackReexecute;
+
+    @HotSpotVMField(name = "Deoptimization::UnrollBlock::_size_of_deoptimized_frame", type = "int", get = HotSpotVMField.Type.OFFSET) @Stable public int deoptimizationUnrollBlockSizeOfDeoptimizedFrameOffset;
+    @HotSpotVMField(name = "Deoptimization::UnrollBlock::_caller_adjustment", type = "int", get = HotSpotVMField.Type.OFFSET) @Stable public int deoptimizationUnrollBlockCallerAdjustmentOffset;
+    @HotSpotVMField(name = "Deoptimization::UnrollBlock::_number_of_frames", type = "int", get = HotSpotVMField.Type.OFFSET) @Stable public int deoptimizationUnrollBlockNumberOfFramesOffset;
+    @HotSpotVMField(name = "Deoptimization::UnrollBlock::_total_frame_sizes", type = "int", get = HotSpotVMField.Type.OFFSET) @Stable public int deoptimizationUnrollBlockTotalFrameSizesOffset;
+    @HotSpotVMField(name = "Deoptimization::UnrollBlock::_frame_sizes", type = "intptr_t*", get = HotSpotVMField.Type.OFFSET) @Stable public int deoptimizationUnrollBlockFrameSizesOffset;
+    @HotSpotVMField(name = "Deoptimization::UnrollBlock::_frame_pcs", type = "address*", get = HotSpotVMField.Type.OFFSET) @Stable public int deoptimizationUnrollBlockFramePcsOffset;
+    @HotSpotVMField(name = "Deoptimization::UnrollBlock::_initial_info", type = "intptr_t", get = HotSpotVMField.Type.OFFSET) @Stable public int deoptimizationUnrollBlockInitialInfoOffset;
+
     @HotSpotVMConstant(name = "vmIntrinsics::_invokeBasic") @Stable public int vmIntrinsicInvokeBasic;
     @HotSpotVMConstant(name = "vmIntrinsics::_linkToVirtual") @Stable public int vmIntrinsicLinkToVirtual;
     @HotSpotVMConstant(name = "vmIntrinsics::_linkToStatic") @Stable public int vmIntrinsicLinkToStatic;
diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotVmSymbols.java
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotVmSymbols.java	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotVmSymbols.java	Mon Apr 28 11:18:15 2014 +0200
@@ -22,7 +22,7 @@
  */
 package com.oracle.graal.hotspot;
 
-import static com.oracle.graal.graph.UnsafeAccess.*;
+import static com.oracle.graal.compiler.common.UnsafeAccess.*;
 import static com.oracle.graal.hotspot.HotSpotGraalRuntime.*;
 import sun.misc.*;
 
diff -r 3dde8d8c95b8 -r 40d0022115ee 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	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/bridge/CompilerToVM.java	Mon Apr 28 11:18:15 2014 +0200
@@ -25,7 +25,7 @@
 
 import com.oracle.graal.api.code.*;
 import com.oracle.graal.api.meta.*;
-import com.oracle.graal.graph.*;
+import com.oracle.graal.compiler.common.*;
 import com.oracle.graal.hotspot.*;
 import com.oracle.graal.hotspot.meta.*;
 
@@ -226,7 +226,7 @@
      * @param code the details of the installed CodeBlob are written to this object
      * @return the outcome of the installation as a {@link CodeInstallResult}.
      */
-    CodeInstallResult installCode(HotSpotCompiledCode compiledCode, HotSpotInstalledCode code, SpeculationLog speculationLog);
+    CodeInstallResult installCode(HotSpotCompiledCode compiledCode, InstalledCode code, SpeculationLog speculationLog);
 
     /**
      * Notifies the VM of statistics for a completed compilation.
@@ -240,7 +240,7 @@
      * @param timeUnitsPerSecond the granularity of the units for the {@code time} value
      * @param installedCode the nmethod installed as a result of the compilation
      */
-    void notifyCompilationStatistics(int id, HotSpotResolvedJavaMethod method, boolean osr, int processedBytecodes, long time, long timeUnitsPerSecond, HotSpotInstalledCode installedCode);
+    void notifyCompilationStatistics(int id, HotSpotResolvedJavaMethod method, boolean osr, int processedBytecodes, long time, long timeUnitsPerSecond, InstalledCode installedCode);
 
     void printCompilationStatistics(boolean perCompiler, boolean aggregate);
 
@@ -270,9 +270,9 @@
 
     StackTraceElement getStackTraceElement(long metaspaceMethod, int bci);
 
-    Object executeCompiledMethod(Object arg1, Object arg2, Object arg3, HotSpotInstalledCode hotspotInstalledCode) throws InvalidInstalledCodeException;
+    Object executeCompiledMethod(Object arg1, Object arg2, Object arg3, InstalledCode hotspotInstalledCode) throws InvalidInstalledCodeException;
 
-    Object executeCompiledMethodVarargs(Object[] args, HotSpotInstalledCode hotspotInstalledCode) throws InvalidInstalledCodeException;
+    Object executeCompiledMethodVarargs(Object[] args, InstalledCode hotspotInstalledCode) throws InvalidInstalledCodeException;
 
     long[] getLineNumberTable(long metaspaceMethod);
 
@@ -284,8 +284,6 @@
 
     Class getJavaMirror(long metaspaceKlass);
 
-    void setNodeClass(Class c, NodeClass nodeClass);
-
     long readUnsafeKlassPointer(Object o);
 
     void doNotInlineOrCompile(long metaspaceMethod);
@@ -297,7 +295,7 @@
      */
     void reprofile(long metaspaceMethod);
 
-    void invalidateInstalledCode(HotSpotInstalledCode hotspotInstalledCode);
+    void invalidateInstalledCode(InstalledCode hotspotInstalledCode);
 
     /**
      * Collects the current values of all Graal benchmark counters, summed up over all threads.
@@ -339,10 +337,11 @@
      * Looks for the next Java stack frame with the given method.
      *
      * @param frame the starting point of the search, where {@code null} refers to the topmost frame
-     * @param method the method to look for, where {@code null} means that any frame is returned
+     * @param methods the metaspace methods to look for, where {@code null} means that any frame is
+     *            returned
      * @return the frame, or {@code null} if the end of the stack was reached during the search
      */
-    HotSpotStackFrameReference getNextStackFrame(HotSpotStackFrameReference frame, HotSpotResolvedJavaMethod method);
+    HotSpotStackFrameReference getNextStackFrame(HotSpotStackFrameReference frame, long[] methods, int initialSkip);
 
     /**
      * Materialized all virtual objects within the given stack frame and update the locals within
@@ -352,4 +351,6 @@
      *            invalidated.
      */
     void materializeVirtualObjects(HotSpotStackFrameReference stackFrame, boolean invalidate);
+
+    void resolveInvokeDynamic(long metaspaceConstantPool, int index);
 }
diff -r 3dde8d8c95b8 -r 40d0022115ee 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	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/bridge/CompilerToVMImpl.java	Mon Apr 28 11:18:15 2014 +0200
@@ -24,7 +24,6 @@
 package com.oracle.graal.hotspot.bridge;
 
 import com.oracle.graal.api.code.*;
-import com.oracle.graal.graph.*;
 import com.oracle.graal.hotspot.*;
 import com.oracle.graal.hotspot.meta.*;
 
@@ -33,10 +32,10 @@
  */
 public class CompilerToVMImpl implements CompilerToVM {
 
-    private native int installCode0(HotSpotCompiledCode compiledCode, HotSpotInstalledCode code, SpeculationLog speculationLog);
+    private native int installCode0(HotSpotCompiledCode compiledCode, InstalledCode code, SpeculationLog speculationLog);
 
     @Override
-    public CodeInstallResult installCode(HotSpotCompiledCode compiledCode, HotSpotInstalledCode code, SpeculationLog speculationLog) {
+    public CodeInstallResult installCode(HotSpotCompiledCode compiledCode, InstalledCode code, SpeculationLog speculationLog) {
         return CodeInstallResult.getEnum(installCode0(compiledCode, code, speculationLog));
     }
 
@@ -121,7 +120,7 @@
     public native StackTraceElement getStackTraceElement(long metaspaceMethod, int bci);
 
     @Override
-    public native Object executeCompiledMethodVarargs(Object[] args, HotSpotInstalledCode hotspotInstalledCode);
+    public native Object executeCompiledMethodVarargs(Object[] args, InstalledCode hotspotInstalledCode);
 
     @Override
     public native long[] getLineNumberTable(long metaspaceMethod);
@@ -139,27 +138,24 @@
     public native void reprofile(long metaspaceMethod);
 
     @Override
-    public native void invalidateInstalledCode(HotSpotInstalledCode hotspotInstalledCode);
+    public native void invalidateInstalledCode(InstalledCode hotspotInstalledCode);
 
     @Override
     public native Class getJavaMirror(long metaspaceKlass);
 
     @Override
-    public native void setNodeClass(Class c, NodeClass nodeClass);
-
-    @Override
     public native long readUnsafeKlassPointer(Object o);
 
     @Override
     public native void doNotInlineOrCompile(long metaspaceMethod);
 
     @Override
-    public Object executeCompiledMethod(Object arg1, Object arg2, Object arg3, HotSpotInstalledCode hotspotInstalledCode) throws InvalidInstalledCodeException {
+    public Object executeCompiledMethod(Object arg1, Object arg2, Object arg3, InstalledCode hotspotInstalledCode) throws InvalidInstalledCodeException {
         return executeCompiledMethodVarargs(new Object[]{arg1, arg2, arg3}, hotspotInstalledCode);
     }
 
     public synchronized native void notifyCompilationStatistics(int id, HotSpotResolvedJavaMethod method, boolean osr, int processedBytecodes, long time, long timeUnitsPerSecond,
-                    HotSpotInstalledCode installedCode);
+                    InstalledCode installedCode);
 
     public synchronized native void printCompilationStatistics(boolean perCompiler, boolean aggregate);
 
@@ -179,9 +175,11 @@
 
     public native boolean hasCompiledCodeForOSR(long metaspaceMethod, int entryBCI, int level);
 
-    public native HotSpotStackFrameReference getNextStackFrame(HotSpotStackFrameReference frame, HotSpotResolvedJavaMethod method);
+    public native HotSpotStackFrameReference getNextStackFrame(HotSpotStackFrameReference frame, long[] methods, int initialSkip);
 
     public native void materializeVirtualObjects(HotSpotStackFrameReference stackFrame, boolean invalidate);
 
     public native long getTimeStamp();
+
+    public native void resolveInvokeDynamic(long metaspaceConstantPool, int index);
 }
diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/bridge/FastNodeClassRegistry.java
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/bridge/FastNodeClassRegistry.java	Fri Apr 25 16:21:07 2014 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,50 +0,0 @@
-/*
- * 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.bridge;
-
-import com.oracle.graal.graph.*;
-import com.oracle.graal.hotspot.replacements.*;
-
-/**
- * Updates the {@code InstanceKlass::_graal_node_class} field when a {@link NodeClass} is created so
- * that the {@link HotSpotNodeClassSubstitutions} and {@link HotSpotNodeSubstitutions}
- * intrinsifications can read it.
- */
-class FastNodeClassRegistry extends NodeClass.Registry {
-
-    private final CompilerToVM vm;
-
-    public FastNodeClassRegistry(CompilerToVM vm) {
-        this.vm = vm;
-    }
-
-    @SuppressWarnings("unused")
-    static void initialize(CompilerToVM vm) {
-        new FastNodeClassRegistry(vm);
-    }
-
-    @Override
-    protected void registered(Class key, NodeClass value) {
-        vm.setNodeClass(key, value);
-    }
-}
diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/bridge/VMToCompiler.java
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/bridge/VMToCompiler.java	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/bridge/VMToCompiler.java	Mon Apr 28 11:18:15 2014 +0200
@@ -38,11 +38,7 @@
 
     void shutdownCompiler() throws Exception;
 
-    /**
-     * @param hostedOnly specifies if the Graal compiler is only being used in hosted mode (i.e., it
-     *            will never compile itself)
-     */
-    void startCompiler(boolean bootstrapEnabled, boolean hostedOnly) throws Throwable;
+    void startCompiler(boolean bootstrapEnabled) throws Throwable;
 
     void bootstrap() throws Throwable;
 
diff -r 3dde8d8c95b8 -r 40d0022115ee 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	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/bridge/VMToCompilerImpl.java	Mon Apr 28 11:18:15 2014 +0200
@@ -34,9 +34,9 @@
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.compiler.*;
 import com.oracle.graal.compiler.CompilerThreadFactory.DebugConfigAccess;
+import com.oracle.graal.compiler.common.*;
 import com.oracle.graal.debug.*;
 import com.oracle.graal.debug.internal.*;
-import com.oracle.graal.graph.*;
 import com.oracle.graal.hotspot.*;
 import com.oracle.graal.hotspot.CompilationTask.Enqueueing;
 import com.oracle.graal.hotspot.CompileTheWorld.Config;
@@ -142,11 +142,7 @@
         this.runtime = runtime;
     }
 
-    public void startCompiler(boolean bootstrapEnabled, boolean hostedOnly) throws Throwable {
-
-        if (!hostedOnly) {
-            FastNodeClassRegistry.initialize(runtime.getCompilerToVM());
-        }
+    public void startCompiler(boolean bootstrapEnabled) throws Throwable {
 
         bootstrapRunning = bootstrapEnabled;
 
@@ -349,7 +345,7 @@
 
     private void enqueue(Method m) throws Throwable {
         JavaMethod javaMethod = runtime.getHostProviders().getMetaAccess().lookupJavaMethod(m);
-        assert !Modifier.isAbstract(((HotSpotResolvedJavaMethod) javaMethod).getModifiers()) && !Modifier.isNative(((HotSpotResolvedJavaMethod) javaMethod).getModifiers()) : javaMethod;
+        assert !((HotSpotResolvedJavaMethod) javaMethod).isAbstract() && !((HotSpotResolvedJavaMethod) javaMethod).isNative() : javaMethod;
         compileMethod((HotSpotResolvedJavaMethod) javaMethod, StructuredGraph.INVOCATION_ENTRY_BCI, false);
     }
 
diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/data/MetaspaceData.java
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/data/MetaspaceData.java	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/data/MetaspaceData.java	Mon Apr 28 11:18:15 2014 +0200
@@ -26,7 +26,7 @@
 
 import com.oracle.graal.api.code.*;
 import com.oracle.graal.api.meta.*;
-import com.oracle.graal.graph.*;
+import com.oracle.graal.compiler.common.*;
 
 /**
  * A data item that represents a metaspace pointer.
diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/data/OopData.java
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/data/OopData.java	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/data/OopData.java	Mon Apr 28 11:18:15 2014 +0200
@@ -26,7 +26,7 @@
 
 import com.oracle.graal.api.code.*;
 import com.oracle.graal.api.meta.*;
-import com.oracle.graal.graph.*;
+import com.oracle.graal.compiler.common.*;
 import com.oracle.graal.hotspot.*;
 import com.oracle.graal.hotspot.nodes.type.*;
 
diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/debug/BenchmarkCounters.java
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/debug/BenchmarkCounters.java	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/debug/BenchmarkCounters.java	Mon Apr 28 11:18:15 2014 +0200
@@ -30,7 +30,8 @@
 import sun.misc.*;
 
 import com.oracle.graal.api.meta.*;
-import com.oracle.graal.graph.*;
+import com.oracle.graal.compiler.common.*;
+import com.oracle.graal.compiler.common.type.*;
 import com.oracle.graal.hotspot.*;
 import com.oracle.graal.hotspot.bridge.*;
 import com.oracle.graal.hotspot.meta.*;
@@ -40,7 +41,6 @@
 import com.oracle.graal.nodes.calc.*;
 import com.oracle.graal.nodes.debug.*;
 import com.oracle.graal.nodes.extended.*;
-import com.oracle.graal.nodes.type.*;
 import com.oracle.graal.options.*;
 import com.oracle.graal.replacements.nodes.*;
 
@@ -99,7 +99,6 @@
 
     private static final boolean DUMP_STATIC = false;
 
-    public static String excludedClassPrefix = null;
     public static boolean enabled = false;
 
     public static final ConcurrentHashMap indexes = new ConcurrentHashMap<>();
@@ -108,14 +107,23 @@
     public static final ArrayList staticCounters = new ArrayList<>();
 
     @SuppressFBWarnings(value = "AT_OPERATION_SEQUENCE_ON_CONCURRENT_ABSTRACTION", justification = "concurrent abstraction calls are in synchronized block")
-    public static int getIndex(DynamicCounterNode counter) {
+    private static int getIndex(DynamicCounterNode counter) {
         if (!enabled) {
             throw new GraalInternalError("counter nodes shouldn't exist when counters are not enabled: " + counter.getGroup() + ", " + counter.getName());
         }
-        String name = counter.getName();
+        String name;
         String group = counter.getGroup();
-        name = counter.isWithContext() && counter.graph().method() != null ? name + " @ " + counter.graph().graphId() + ":" + MetaUtil.format("%h.%n", counter.graph().method()) + "#" + group : name +
-                        "#" + group;
+        if (counter.isWithContext()) {
+            StructuredGraph graph = counter.graph();
+            name = counter.getName() + " @ " + graph.graphId() + ":" + (graph.method() == null ? "" : MetaUtil.format("%h.%n", graph.method()));
+            if (graph.name != null) {
+                name += " (" + graph.name + ")";
+            }
+            name += "#" + group;
+
+        } else {
+            name = counter.getName() + "#" + group;
+        }
         Integer index = indexes.get(name);
         if (index == null) {
             synchronized (BenchmarkCounters.class) {
@@ -135,7 +143,7 @@
         return index;
     }
 
-    public static synchronized void dump(PrintStream out, double seconds, long[] counters, int maxRows) {
+    private static synchronized void dump(PrintStream out, double seconds, long[] counters, int maxRows) {
         if (!groups.isEmpty()) {
             out.println("====== dynamic counters (" + staticCounters.size() + " in total) ======");
             for (String group : new TreeSet<>(groups)) {
@@ -152,7 +160,7 @@
         }
     }
 
-    public static synchronized void clear(long[] counters) {
+    private static synchronized void clear(long[] counters) {
         delta = counters;
     }
 
@@ -228,7 +236,7 @@
         return (counter * 200 + 1) / sum / 2;
     }
 
-    public abstract static class CallbackOutputStream extends OutputStream {
+    private abstract static class CallbackOutputStream extends OutputStream {
 
         protected final PrintStream delegate;
         private final byte[][] patterns;
@@ -281,25 +289,30 @@
         final class BenchmarkCountersOutputStream extends CallbackOutputStream {
 
             private long startTime;
+            private boolean running;
             private boolean waitingForEnd;
 
             private BenchmarkCountersOutputStream(PrintStream delegate, String start, String end) {
-                super(delegate, new String[]{start, end, "\n"});
+                super(delegate, new String[]{"\n", end, start});
             }
 
             @Override
             protected void patternFound(int index) {
                 switch (index) {
-                    case 0:
+                    case 2:
                         startTime = System.nanoTime();
                         BenchmarkCounters.clear(compilerToVM.collectCounters());
+                        running = true;
                         break;
                     case 1:
-                        waitingForEnd = true;
+                        if (running) {
+                            waitingForEnd = true;
+                        }
                         break;
-                    case 2:
+                    case 0:
                         if (waitingForEnd) {
                             waitingForEnd = false;
+                            running = false;
                             BenchmarkCounters.dump(delegate, (System.nanoTime() - startTime) / 1000000000d, compilerToVM.collectCounters(), 100);
                         }
                         break;
@@ -321,7 +334,6 @@
                     throw new GraalInternalError("invalid arguments to BenchmarkDynamicCounters: err|out");
                 }
             }
-            excludedClassPrefix = "Lcom/oracle/graal/";
             enabled = true;
         }
         if (Options.GenericDynamicCounters.getValue()) {
@@ -363,26 +375,24 @@
 
     public static void lower(DynamicCounterNode counter, HotSpotRegistersProvider registers, HotSpotVMConfig config, Kind wordKind) {
         StructuredGraph graph = counter.graph();
-        if (excludedClassPrefix == null || (counter.graph().method() != null && !counter.graph().method().getDeclaringClass().getName().startsWith(excludedClassPrefix))) {
 
-            ReadRegisterNode thread = graph.add(new ReadRegisterNode(registers.getThreadRegister(), wordKind, true, false));
+        ReadRegisterNode thread = graph.add(new ReadRegisterNode(registers.getThreadRegister(), wordKind, true, false));
 
-            int index = BenchmarkCounters.getIndex(counter);
-            if (index >= config.graalCountersSize) {
-                throw new GraalInternalError("too many counters, reduce number of counters or increase -XX:GraalCounterSize=... (current value: " + config.graalCountersSize + ")");
-            }
-            ConstantLocationNode arrayLocation = ConstantLocationNode.create(LocationIdentity.ANY_LOCATION, Kind.Long, config.graalCountersThreadOffset, graph);
-            ReadNode readArray = graph.add(new ReadNode(thread, arrayLocation, StampFactory.forKind(wordKind), BarrierType.NONE, false));
-            ConstantLocationNode location = ConstantLocationNode.create(LocationIdentity.ANY_LOCATION, Kind.Long, Unsafe.ARRAY_LONG_INDEX_SCALE * index, graph);
-            ReadNode read = graph.add(new ReadNode(readArray, location, StampFactory.forKind(Kind.Long), BarrierType.NONE, false));
-            IntegerAddNode add = graph.unique(new IntegerAddNode(StampFactory.forKind(Kind.Long), read, counter.getIncrement()));
-            WriteNode write = graph.add(new WriteNode(readArray, add, location, BarrierType.NONE, false));
+        int index = BenchmarkCounters.getIndex(counter);
+        if (index >= config.graalCountersSize) {
+            throw new GraalInternalError("too many counters, reduce number of counters or increase -XX:GraalCounterSize=... (current value: " + config.graalCountersSize + ")");
+        }
+        ConstantLocationNode arrayLocation = ConstantLocationNode.create(LocationIdentity.ANY_LOCATION, wordKind, config.graalCountersThreadOffset, graph);
+        ReadNode readArray = graph.add(new ReadNode(thread, arrayLocation, StampFactory.forKind(wordKind), BarrierType.NONE, false));
+        ConstantLocationNode location = ConstantLocationNode.create(LocationIdentity.ANY_LOCATION, Kind.Long, Unsafe.ARRAY_LONG_INDEX_SCALE * index, graph);
+        ReadNode read = graph.add(new ReadNode(readArray, location, StampFactory.forKind(Kind.Long), BarrierType.NONE, false));
+        IntegerAddNode add = graph.unique(new IntegerAddNode(StampFactory.forKind(Kind.Long), read, counter.getIncrement()));
+        WriteNode write = graph.add(new WriteNode(readArray, add, location, BarrierType.NONE, false));
 
-            graph.addBeforeFixed(counter, thread);
-            graph.addBeforeFixed(counter, readArray);
-            graph.addBeforeFixed(counter, read);
-            graph.addBeforeFixed(counter, write);
-        }
+        graph.addBeforeFixed(counter, thread);
+        graph.addBeforeFixed(counter, readArray);
+        graph.addBeforeFixed(counter, read);
+        graph.addBeforeFixed(counter, write);
         graph.removeFixed(counter);
     }
 }
diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/DefaultHotSpotLoweringProvider.java
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/DefaultHotSpotLoweringProvider.java	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/DefaultHotSpotLoweringProvider.java	Mon Apr 28 11:18:15 2014 +0200
@@ -26,18 +26,20 @@
 import static com.oracle.graal.api.meta.DeoptimizationAction.*;
 import static com.oracle.graal.api.meta.DeoptimizationReason.*;
 import static com.oracle.graal.api.meta.LocationIdentity.*;
+import static com.oracle.graal.compiler.common.GraalOptions.*;
 import static com.oracle.graal.hotspot.HotSpotGraalRuntime.*;
 import static com.oracle.graal.hotspot.meta.HotSpotForeignCallsProviderImpl.*;
 import static com.oracle.graal.hotspot.replacements.HotSpotReplacementsUtil.*;
 import static com.oracle.graal.hotspot.replacements.NewObjectSnippets.*;
 import static com.oracle.graal.nodes.java.ArrayLengthNode.*;
-import static com.oracle.graal.phases.GraalOptions.*;
 
 import java.util.*;
 
 import com.oracle.graal.api.code.*;
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.asm.*;
+import com.oracle.graal.compiler.common.*;
+import com.oracle.graal.compiler.common.type.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.hotspot.*;
 import com.oracle.graal.hotspot.debug.*;
@@ -110,6 +112,8 @@
             lowerStoreFieldNode((StoreFieldNode) n, tool);
         } else if (n instanceof CompareAndSwapNode) {
             lowerCompareAndSwapNode((CompareAndSwapNode) n);
+        } else if (n instanceof AtomicReadAndWriteNode) {
+            lowerAtomicReadAndWriteNode((AtomicReadAndWriteNode) n);
         } else if (n instanceof LoadIndexedNode) {
             lowerLoadIndexedNode((LoadIndexedNode) n, tool);
         } else if (n instanceof StoreIndexedNode) {
@@ -188,8 +192,10 @@
             if (graph.getGuardsStage() == StructuredGraph.GuardsStage.AFTER_FSA) {
                 newObjectSnippets.lower((NewMultiArrayNode) n, tool);
             }
-        } else if (n instanceof LoadExceptionObjectNode) {
-            exceptionObjectSnippets.lower((LoadExceptionObjectNode) n, registers, tool);
+        } else if (n instanceof ExceptionObjectNode) {
+            if (graph.getGuardsStage() == StructuredGraph.GuardsStage.FIXED_DEOPTS) {
+                lowerExceptionObjectNode((ExceptionObjectNode) 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.
@@ -219,7 +225,7 @@
             NodeInputList parameters = callTarget.arguments();
             ValueNode receiver = parameters.size() <= 0 ? null : parameters.get(0);
             GuardingNode receiverNullCheck = null;
-            if (!callTarget.isStatic() && receiver.stamp() instanceof ObjectStamp && !ObjectStamp.isObjectNonNull(receiver)) {
+            if (!callTarget.isStatic() && receiver.stamp() instanceof ObjectStamp && !StampTool.isObjectNonNull(receiver)) {
                 receiverNullCheck = createNullCheck(receiver, invoke.asNode(), tool);
                 invoke.setGuard(receiverNullCheck);
             }
@@ -378,11 +384,27 @@
         ValueNode expectedValue = implicitStoreConvert(graph, valueKind, cas.expected(), true);
         ValueNode newValue = implicitStoreConvert(graph, valueKind, cas.newValue(), true);
 
-        LoweredCompareAndSwapNode atomicNode = graph.add(new LoweredCompareAndSwapNode(cas.object(), location, expectedValue, newValue, getCompareAndSwapBarrier(cas), false));
+        LoweredCompareAndSwapNode atomicNode = graph.add(new LoweredCompareAndSwapNode(cas.object(), location, expectedValue, newValue, getCompareAndSwapBarrierType(cas), false));
         atomicNode.setStateAfter(cas.stateAfter());
         graph.replaceFixedWithFixed(cas, atomicNode);
     }
 
+    private void lowerAtomicReadAndWriteNode(AtomicReadAndWriteNode n) {
+        StructuredGraph graph = n.graph();
+        Kind valueKind = n.getValueKind();
+        LocationNode location = IndexedLocationNode.create(n.getLocationIdentity(), valueKind, 0, n.offset(), graph, 1);
+
+        ValueNode newValue = implicitStoreConvert(graph, valueKind, n.newValue());
+
+        LoweredAtomicReadAndWriteNode memoryRead = graph.add(new LoweredAtomicReadAndWriteNode(n.object(), location, newValue, getAtomicReadAndWriteBarrierType(n), false));
+        memoryRead.setStateAfter(n.stateAfter());
+
+        ValueNode readValue = implicitLoadConvert(graph, valueKind, memoryRead);
+
+        n.replaceAtUsages(readValue);
+        graph.replaceFixedWithFixed(n, memoryRead);
+    }
+
     private void lowerLoadIndexedNode(LoadIndexedNode loadIndexed, LoweringTool tool) {
         StructuredGraph graph = loadIndexed.graph();
         Kind elementKind = loadIndexed.elementKind();
@@ -409,10 +431,10 @@
 
         CheckCastNode checkcastNode = null;
         CheckCastDynamicNode checkcastDynamicNode = null;
-        if (elementKind == Kind.Object && !ObjectStamp.isObjectAlwaysNull(value)) {
+        if (elementKind == Kind.Object && !StampTool.isObjectAlwaysNull(value)) {
             // Store check!
-            ResolvedJavaType arrayType = ObjectStamp.typeOrNull(array);
-            if (arrayType != null && ObjectStamp.isExactType(array)) {
+            ResolvedJavaType arrayType = StampTool.typeOrNull(array);
+            if (arrayType != null && StampTool.isExactType(array)) {
                 ResolvedJavaType elementType = arrayType.getComponentType();
                 if (!MetaUtil.isJavaLangObject(elementType)) {
                     checkcastNode = graph.add(new CheckCastNode(elementType, value, null, true));
@@ -474,7 +496,7 @@
                 ReadNode memoryRead = createUnsafeRead(graph, load, null);
                 // An unsafe read must not float outside its block otherwise
                 // it may float above an explicit null check on its object.
-                memoryRead.setGuard(AbstractBeginNode.prevBegin(load));
+                memoryRead.setGuard(BeginNode.prevBegin(load));
                 graph.replaceFixedWithFixed(load, memoryRead);
             }
         }
@@ -712,6 +734,19 @@
         }
     }
 
+    private void lowerExceptionObjectNode(ExceptionObjectNode n, LoweringTool tool) {
+        LocationIdentity locationsKilledByInvoke = ((InvokeWithExceptionNode) n.predecessor()).getLocationIdentity();
+        BeginNode entry = n.graph().add(new KillingBeginNode(locationsKilledByInvoke));
+        LoadExceptionObjectNode loadException = n.graph().add(new LoadExceptionObjectNode(StampFactory.declaredNonNull(metaAccess.lookupJavaType(Throwable.class))));
+
+        loadException.setStateAfter(n.stateAfter());
+        n.replaceAtUsages(InputType.Value, loadException);
+        n.graph().replaceFixedWithFixed(n, entry);
+        entry.graph().addAfterFixed(entry, loadException);
+
+        exceptionObjectSnippets.lower(loadException, registers, tool);
+    }
+
     public static void finishAllocatedObjects(LoweringTool tool, CommitAllocationNode commit, ValueNode[] allocations) {
         StructuredGraph graph = commit.graph();
         for (int objIndex = 0; objIndex < commit.getVirtualObjects().size(); objIndex++) {
@@ -787,8 +822,8 @@
 
     private static boolean addReadBarrier(UnsafeLoadNode load) {
         if (useG1GC() && load.graph().getGuardsStage() == StructuredGraph.GuardsStage.FIXED_DEOPTS && load.object().getKind() == Kind.Object && load.accessKind() == Kind.Object &&
-                        !ObjectStamp.isObjectAlwaysNull(load.object())) {
-            ResolvedJavaType type = ObjectStamp.typeOrNull(load.object());
+                        !StampTool.isObjectAlwaysNull(load.object())) {
+            ResolvedJavaType type = StampTool.typeOrNull(load.object());
             if (type != null && !type.isArray()) {
                 return true;
             }
@@ -816,7 +851,7 @@
 
         Stamp hubStamp;
         if (config.useCompressedClassPointers) {
-            hubStamp = StampFactory.forInteger(32, false);
+            hubStamp = StampFactory.forInteger(32);
         } else {
             hubStamp = StampFactory.forKind(wordKind);
         }
@@ -851,45 +886,53 @@
     }
 
     private static BarrierType getFieldStoreBarrierType(StoreFieldNode storeField) {
-        BarrierType barrierType = BarrierType.NONE;
         if (storeField.field().getKind() == Kind.Object) {
-            barrierType = BarrierType.IMPRECISE;
+            return BarrierType.IMPRECISE;
         }
-        return barrierType;
+        return BarrierType.NONE;
     }
 
     private static BarrierType getArrayStoreBarrierType(StoreIndexedNode store) {
-        BarrierType barrierType = BarrierType.NONE;
         if (store.elementKind() == Kind.Object) {
-            barrierType = BarrierType.PRECISE;
+            return BarrierType.PRECISE;
         }
-        return barrierType;
+        return BarrierType.NONE;
     }
 
     private static BarrierType getUnsafeStoreBarrierType(UnsafeStoreNode store) {
-        BarrierType barrierType = BarrierType.NONE;
         if (store.value().getKind() == Kind.Object) {
-            ResolvedJavaType type = ObjectStamp.typeOrNull(store.object());
+            ResolvedJavaType type = StampTool.typeOrNull(store.object());
             if (type != null && !type.isArray()) {
-                barrierType = BarrierType.IMPRECISE;
+                return BarrierType.IMPRECISE;
             } else {
-                barrierType = BarrierType.PRECISE;
+                return BarrierType.PRECISE;
             }
         }
-        return barrierType;
+        return BarrierType.NONE;
     }
 
-    private static BarrierType getCompareAndSwapBarrier(CompareAndSwapNode cas) {
-        BarrierType barrierType = BarrierType.NONE;
+    private static BarrierType getCompareAndSwapBarrierType(CompareAndSwapNode cas) {
         if (cas.expected().getKind() == Kind.Object) {
-            ResolvedJavaType type = ObjectStamp.typeOrNull(cas.object());
+            ResolvedJavaType type = StampTool.typeOrNull(cas.object());
             if (type != null && !type.isArray()) {
-                barrierType = BarrierType.IMPRECISE;
+                return BarrierType.IMPRECISE;
             } else {
-                barrierType = BarrierType.PRECISE;
+                return BarrierType.PRECISE;
             }
         }
-        return barrierType;
+        return BarrierType.NONE;
+    }
+
+    private static BarrierType getAtomicReadAndWriteBarrierType(AtomicReadAndWriteNode n) {
+        if (n.newValue().getKind() == Kind.Object) {
+            ResolvedJavaType type = StampTool.typeOrNull(n.object());
+            if (type != null && !type.isArray()) {
+                return BarrierType.IMPRECISE;
+            } else {
+                return BarrierType.PRECISE;
+            }
+        }
+        return BarrierType.NONE;
     }
 
     protected static ConstantLocationNode createFieldLocation(StructuredGraph graph, HotSpotResolvedJavaField field, boolean initialization) {
@@ -976,7 +1019,7 @@
     }
 
     private static GuardingNode createNullCheck(ValueNode object, FixedNode before, LoweringTool tool) {
-        if (ObjectStamp.isObjectNonNull(object)) {
+        if (StampTool.isObjectNonNull(object)) {
             return null;
         }
         return tool.createGuard(before, before.graph().unique(new IsNullNode(object)), DeoptimizationReason.NullCheckException, DeoptimizationAction.InvalidateReprofile, true);
diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotCodeCacheProvider.java
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotCodeCacheProvider.java	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotCodeCacheProvider.java	Mon Apr 28 11:18:15 2014 +0200
@@ -35,8 +35,8 @@
 import com.oracle.graal.api.code.CompilationResult.Mark;
 import com.oracle.graal.api.code.CompilationResult.PrimitiveData;
 import com.oracle.graal.api.meta.*;
+import com.oracle.graal.compiler.common.*;
 import com.oracle.graal.debug.*;
-import com.oracle.graal.graph.*;
 import com.oracle.graal.hotspot.*;
 import com.oracle.graal.hotspot.bridge.*;
 import com.oracle.graal.hotspot.bridge.CompilerToVM.CodeInstallResult;
@@ -196,7 +196,7 @@
         return runtime.getConfig().runtimeCallStackSize;
     }
 
-    public HotSpotInstalledCode logOrDump(HotSpotInstalledCode installedCode, CompilationResult compResult) {
+    public InstalledCode logOrDump(InstalledCode installedCode, CompilationResult compResult) {
         if (Debug.isDumpEnabled()) {
             Debug.dump(new Object[]{compResult, installedCode}, "After code installation");
         }
@@ -206,7 +206,7 @@
         return installedCode;
     }
 
-    public HotSpotInstalledCode installMethod(HotSpotResolvedJavaMethod method, CompilationResult compResult) {
+    public InstalledCode installMethod(HotSpotResolvedJavaMethod method, CompilationResult compResult) {
         if (compResult.getId() == -1) {
             compResult.setId(method.allocateCompileId(compResult.getEntryBCI()));
         }
@@ -216,17 +216,21 @@
     }
 
     @Override
-    public InstalledCode addMethod(ResolvedJavaMethod method, CompilationResult compResult, SpeculationLog log) {
+    public InstalledCode addMethod(ResolvedJavaMethod method, CompilationResult compResult, SpeculationLog log, InstalledCode predefinedInstalledCode) {
         HotSpotResolvedJavaMethod hotspotMethod = (HotSpotResolvedJavaMethod) method;
         if (compResult.getId() == -1) {
             compResult.setId(hotspotMethod.allocateCompileId(compResult.getEntryBCI()));
         }
-        HotSpotInstalledCode code = new HotSpotNmethod(hotspotMethod, compResult.getName(), false);
-        CodeInstallResult result = runtime.getCompilerToVM().installCode(new HotSpotCompiledNmethod(target, hotspotMethod, compResult), code, log);
+        InstalledCode installedCode = predefinedInstalledCode;
+        if (installedCode == null) {
+            HotSpotInstalledCode code = new HotSpotNmethod(hotspotMethod, compResult.getName(), false);
+            installedCode = code;
+        }
+        CodeInstallResult result = runtime.getCompilerToVM().installCode(new HotSpotCompiledNmethod(target, hotspotMethod, compResult), installedCode, log);
         if (result != CodeInstallResult.OK) {
-            return null;
+            throw new BailoutException("Code installation failed: " + result);
         }
-        return logOrDump(code, compResult);
+        return logOrDump(installedCode, compResult);
     }
 
     @Override
@@ -256,7 +260,9 @@
 
     public Data createDataItem(Constant constant, int alignment) {
         if (constant instanceof HotSpotMetaspaceConstant) {
-            return new MetaspaceData(alignment, constant.asLong(), HotSpotMetaspaceConstant.getMetaspaceObject(constant), false);
+            // constant.getKind() == target.wordKind for uncompressed pointers
+            // otherwise, it's a compressed pointer
+            return new MetaspaceData(alignment, constant.asLong(), HotSpotMetaspaceConstant.getMetaspaceObject(constant), constant.getKind() != target.wordKind);
         } else if (constant.getKind().isObject()) {
             return new OopData(alignment, HotSpotObjectConstant.asObject(constant), false);
         } else {
@@ -271,7 +277,7 @@
 
     public String disassemble(InstalledCode code) {
         if (code.isValid()) {
-            long codeBlob = ((HotSpotInstalledCode) code).getCodeBlob();
+            long codeBlob = ((HotSpotInstalledCode) code).getAddress();
             return runtime.getCompilerToVM().disassembleCodeBlob(codeBlob);
         }
         return null;
@@ -280,4 +286,8 @@
     public String disassemble(ResolvedJavaMethod method) {
         return new BytecodeDisassembler().disassemble(method);
     }
+
+    public SpeculationLog createSpeculationLog() {
+        return new HotSpotSpeculationLog();
+    }
 }
diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotConstantPool.java
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotConstantPool.java	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotConstantPool.java	Mon Apr 28 11:18:15 2014 +0200
@@ -22,14 +22,14 @@
  */
 package com.oracle.graal.hotspot.meta;
 
-import static com.oracle.graal.graph.UnsafeAccess.*;
+import static com.oracle.graal.compiler.common.UnsafeAccess.*;
 import static com.oracle.graal.hotspot.HotSpotGraalRuntime.*;
 
 import java.lang.invoke.*;
 
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.bytecode.*;
-import com.oracle.graal.graph.*;
+import com.oracle.graal.compiler.common.*;
 import com.oracle.graal.hotspot.*;
 
 /**
@@ -501,7 +501,7 @@
                 break;
             case Bytecodes.INVOKEDYNAMIC:
                 // invokedynamic instructions point to a constant pool cache entry.
-                index = decodeConstantPoolCacheIndex(cpi);
+                index = decodeConstantPoolCacheIndex(cpi) + runtime().getConfig().constantPoolCpCacheIndexTag;
                 index = runtime().getCompilerToVM().constantPoolRemapInstructionOperandFromCache(metaspaceConstantPool, index);
                 break;
             default:
@@ -517,13 +517,7 @@
                 index = getUncachedKlassRefIndexAt(index);
                 tag = getTagAt(index);
                 assert tag == JVM_CONSTANT.Class || tag == JVM_CONSTANT.UnresolvedClass || tag == JVM_CONSTANT.UnresolvedClassInError : tag;
-                break;
-            default:
-                // nothing
-                break;
-        }
-
-        switch (tag) {
+                // fall-through
             case Class:
             case UnresolvedClass:
             case UnresolvedClassInError:
@@ -534,6 +528,12 @@
                     unsafe.ensureClassInitialized(klass);
                 }
                 break;
+            case InvokeDynamic:
+                if (!isInvokedynamicIndex(cpi)) {
+                    throw new IllegalArgumentException("InvokeDynamic entries must be accessed");
+                }
+                runtime().getCompilerToVM().resolveInvokeDynamic(metaspaceConstantPool, cpi);
+                break;
             default:
                 // nothing
                 break;
diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotConstantReflectionProvider.java
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotConstantReflectionProvider.java	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotConstantReflectionProvider.java	Mon Apr 28 11:18:15 2014 +0200
@@ -22,13 +22,13 @@
  */
 package com.oracle.graal.hotspot.meta;
 
-import static com.oracle.graal.graph.UnsafeAccess.*;
+import static com.oracle.graal.compiler.common.UnsafeAccess.*;
 import static com.oracle.graal.hotspot.replacements.HotSpotReplacementsUtil.*;
 
 import java.lang.reflect.*;
 
 import com.oracle.graal.api.meta.*;
-import com.oracle.graal.graph.*;
+import com.oracle.graal.compiler.common.*;
 import com.oracle.graal.hotspot.*;
 
 /**
diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotDisassemblerProvider.java
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotDisassemblerProvider.java	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotDisassemblerProvider.java	Mon Apr 28 11:18:15 2014 +0200
@@ -38,7 +38,7 @@
 
     public String disassemble(InstalledCode code) {
         if (code.isValid()) {
-            long codeBlob = ((HotSpotInstalledCode) code).getCodeBlob();
+            long codeBlob = ((HotSpotInstalledCode) code).getAddress();
             return runtime.getCompilerToVM().disassembleCodeBlob(codeBlob);
         }
         return null;
diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotHostForeignCallsProvider.java
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotHostForeignCallsProvider.java	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotHostForeignCallsProvider.java	Mon Apr 28 11:18:15 2014 +0200
@@ -30,6 +30,7 @@
 import static com.oracle.graal.hotspot.nodes.NewArrayStubCall.*;
 import static com.oracle.graal.hotspot.nodes.NewInstanceStubCall.*;
 import static com.oracle.graal.hotspot.nodes.NewMultiArrayStubCall.*;
+import static com.oracle.graal.hotspot.nodes.UncommonTrapCallNode.*;
 import static com.oracle.graal.hotspot.nodes.VMErrorNode.*;
 import static com.oracle.graal.hotspot.replacements.HotSpotReplacementsUtil.*;
 import static com.oracle.graal.hotspot.replacements.MonitorSnippets.*;
@@ -37,6 +38,7 @@
 import static com.oracle.graal.hotspot.replacements.SystemSubstitutions.*;
 import static com.oracle.graal.hotspot.replacements.ThreadSubstitutions.*;
 import static com.oracle.graal.hotspot.replacements.WriteBarrierSnippets.*;
+import static com.oracle.graal.hotspot.stubs.DeoptimizationStub.*;
 import static com.oracle.graal.hotspot.stubs.ExceptionHandlerStub.*;
 import static com.oracle.graal.hotspot.stubs.NewArrayStub.*;
 import static com.oracle.graal.hotspot.stubs.NewInstanceStub.*;
@@ -64,7 +66,7 @@
         super(runtime, metaAccess, codeCache);
     }
 
-    private static void link(Stub stub) {
+    protected static void link(Stub stub) {
         stub.getLinkage().setCompiledStub(stub);
     }
 
@@ -101,7 +103,6 @@
     public void initialize(HotSpotProviders providers, HotSpotVMConfig c) {
         TargetDescription target = providers.getCodeCache().getTarget();
 
-        registerForeignCall(UNCOMMON_TRAP, c.uncommonTrapStub, NativeCall, PRESERVES_REGISTERS, LEAF_NOFP, REEXECUTABLE, NO_LOCATIONS);
         registerForeignCall(DEOPT_HANDLER, c.handleDeoptStub, NativeCall, PRESERVES_REGISTERS, LEAF_NOFP, REEXECUTABLE, NO_LOCATIONS);
         registerForeignCall(IC_MISS_HANDLER, c.inlineCacheMissStub(), NativeCall, PRESERVES_REGISTERS, LEAF_NOFP, REEXECUTABLE, NO_LOCATIONS);
 
@@ -114,8 +115,18 @@
 
         registerForeignCall(EXCEPTION_HANDLER_FOR_PC, c.exceptionHandlerForPcAddress, NativeCall, DESTROYS_REGISTERS, NOT_LEAF, REEXECUTABLE, ANY_LOCATION);
         registerForeignCall(EXCEPTION_HANDLER_FOR_RETURN_ADDRESS, c.exceptionHandlerForReturnAddressAddress, NativeCall, DESTROYS_REGISTERS, NOT_LEAF, REEXECUTABLE, ANY_LOCATION);
+        registerForeignCall(FETCH_UNROLL_INFO, c.deoptimizationFetchUnrollInfo, NativeCall, DESTROYS_REGISTERS, NOT_LEAF, REEXECUTABLE, ANY_LOCATION);
         registerForeignCall(NEW_ARRAY_C, c.newArrayAddress, NativeCall, DESTROYS_REGISTERS, NOT_LEAF, REEXECUTABLE, ANY_LOCATION);
         registerForeignCall(NEW_INSTANCE_C, c.newInstanceAddress, NativeCall, DESTROYS_REGISTERS, NOT_LEAF, REEXECUTABLE, ANY_LOCATION);
+        registerForeignCall(UNCOMMON_TRAP, c.deoptimizationUncommonTrap, NativeCall, DESTROYS_REGISTERS, NOT_LEAF, NOT_REEXECUTABLE, ANY_LOCATION);
+
+        /*
+         * We cannot use LEAF_SP here because on some architectures we have to align the stack
+         * manually before calling into the VM. See {@link
+         * AMD64HotSpotEnterUnpackFramesStackFrameOp#emitCode}.
+         */
+        registerForeignCall(UNPACK_FRAMES, c.deoptimizationUnpackFrames, NativeCall, DESTROYS_REGISTERS, LEAF, NOT_REEXECUTABLE, ANY_LOCATION);
+
         registerForeignCall(VM_MESSAGE_C, c.vmMessageAddress, NativeCall, DESTROYS_REGISTERS, NOT_LEAF, REEXECUTABLE, NO_LOCATIONS);
 
         link(new NewInstanceStub(providers, target, registerStubCall(NEW_INSTANCE, REEXECUTABLE, NOT_LEAF, ANY_LOCATION)));
diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotInstalledCode.java
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotInstalledCode.java	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotInstalledCode.java	Mon Apr 28 11:18:15 2014 +0200
@@ -22,45 +22,32 @@
  */
 package com.oracle.graal.hotspot.meta;
 
-import static com.oracle.graal.graph.UnsafeAccess.*;
+import static com.oracle.graal.compiler.common.UnsafeAccess.*;
 import sun.misc.*;
 
 import com.oracle.graal.api.code.*;
-import com.oracle.graal.hotspot.*;
+
+import edu.umd.cs.findbugs.annotations.*;
 
 /**
  * Implementation of {@link InstalledCode} for HotSpot.
  */
-public abstract class HotSpotInstalledCode extends CompilerObject implements InstalledCode {
-
-    private static final long serialVersionUID = 156632908220561612L;
-
-    /**
-     * Raw address of this code blob.
-     */
-    private long codeBlob;
+public abstract class HotSpotInstalledCode extends InstalledCode {
 
     /**
      * Total size of the code blob.
      */
-    private int size;
+    @SuppressFBWarnings(value = "UWF_UNWRITTEN_FIELD", justification = "field is set by the native part") private int size;
 
     /**
      * Start address of the code.
      */
-    private long codeStart;
+    @SuppressFBWarnings(value = "UWF_UNWRITTEN_FIELD", justification = "field is set by the native part") private long codeStart;
 
     /**
      * Size of the code.
      */
-    private int codeSize;
-
-    /**
-     * @return the address of this code blob
-     */
-    public long getCodeBlob() {
-        return codeBlob;
-    }
+    @SuppressFBWarnings(value = "UWF_UNWRITTEN_FIELD", justification = "field is set by the native part") private int codeSize;
 
     /**
      * @return the total size of this code blob
@@ -77,13 +64,14 @@
             return null;
         }
         byte[] blob = new byte[size];
-        unsafe.copyMemory(null, codeBlob, blob, Unsafe.ARRAY_BYTE_BASE_OFFSET, size);
+        unsafe.copyMemory(null, getAddress(), blob, Unsafe.ARRAY_BYTE_BASE_OFFSET, size);
         return blob;
     }
 
     @Override
     public abstract String toString();
 
+    @Override
     public long getStart() {
         return codeStart;
     }
@@ -92,6 +80,7 @@
         return codeSize;
     }
 
+    @Override
     public byte[] getCode() {
         if (!isValid()) {
             return null;
diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotLoweringProvider.java
diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotMetaAccessProvider.java
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotMetaAccessProvider.java	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotMetaAccessProvider.java	Mon Apr 28 11:18:15 2014 +0200
@@ -22,13 +22,13 @@
  */
 package com.oracle.graal.hotspot.meta;
 
-import static com.oracle.graal.graph.UnsafeAccess.*;
+import static com.oracle.graal.compiler.common.UnsafeAccess.*;
 
 import java.lang.reflect.*;
 
 import com.oracle.graal.api.code.*;
 import com.oracle.graal.api.meta.*;
-import com.oracle.graal.graph.*;
+import com.oracle.graal.compiler.common.*;
 import com.oracle.graal.hotspot.*;
 import com.oracle.graal.hotspot.replacements.*;
 
diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotMethodData.java
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotMethodData.java	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotMethodData.java	Mon Apr 28 11:18:15 2014 +0200
@@ -22,7 +22,7 @@
  */
 package com.oracle.graal.hotspot.meta;
 
-import static com.oracle.graal.graph.UnsafeAccess.*;
+import static com.oracle.graal.compiler.common.UnsafeAccess.*;
 import static com.oracle.graal.hotspot.HotSpotGraalRuntime.*;
 import static java.lang.String.*;
 
diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotMethodDataAccessor.java
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotMethodDataAccessor.java	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotMethodDataAccessor.java	Mon Apr 28 11:18:15 2014 +0200
@@ -26,7 +26,7 @@
 
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.api.meta.ProfilingInfo.TriState;
-import com.oracle.graal.graph.*;
+import com.oracle.graal.compiler.common.*;
 import com.oracle.graal.hotspot.*;
 
 /**
diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotNmethod.java
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotNmethod.java	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotNmethod.java	Mon Apr 28 11:18:15 2014 +0200
@@ -24,8 +24,6 @@
 
 import static com.oracle.graal.hotspot.HotSpotGraalRuntime.*;
 
-import java.lang.reflect.*;
-
 import com.oracle.graal.api.code.*;
 import com.oracle.graal.api.meta.*;
 
@@ -40,8 +38,6 @@
  */
 public final class HotSpotNmethod extends HotSpotInstalledCode {
 
-    private static final long serialVersionUID = -1784683588947054103L;
-
     /**
      * This (indirect) Method* reference is safe since class redefinition preserves all methods
      * associated with nmethods in the code cache.
@@ -71,31 +67,25 @@
         return isExternal;
     }
 
-    @Override
     public ResolvedJavaMethod getMethod() {
         return method;
     }
 
     @Override
-    public boolean isValid() {
-        return getCodeBlob() != 0;
-    }
-
-    @Override
     public void invalidate() {
         runtime().getCompilerToVM().invalidateInstalledCode(this);
     }
 
     @Override
     public String toString() {
-        return String.format("InstalledNmethod[method=%s, codeBlob=0x%x, isDefault=%b, name=%s]", method, getCodeBlob(), isDefault, name);
+        return String.format("InstalledNmethod[method=%s, codeBlob=0x%x, isDefault=%b, name=%s]", method, getAddress(), isDefault, name);
     }
 
     protected boolean checkThreeObjectArgs() {
-        assert method.getSignature().getParameterCount(!Modifier.isStatic(method.getModifiers())) == 3;
+        assert method.getSignature().getParameterCount(!method.isStatic()) == 3;
         assert method.getSignature().getParameterKind(0) == Kind.Object;
         assert method.getSignature().getParameterKind(1) == Kind.Object;
-        assert !Modifier.isStatic(method.getModifiers()) || method.getSignature().getParameterKind(2) == Kind.Object;
+        assert !method.isStatic() || method.getSignature().getParameterKind(2) == Kind.Object;
         return true;
     }
 
diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotResolvedJavaField.java
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotResolvedJavaField.java	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotResolvedJavaField.java	Mon Apr 28 11:18:15 2014 +0200
@@ -23,17 +23,16 @@
 package com.oracle.graal.hotspot.meta;
 
 import static com.oracle.graal.api.meta.MetaUtil.*;
+import static com.oracle.graal.compiler.common.GraalOptions.*;
 import static com.oracle.graal.hotspot.HotSpotGraalRuntime.*;
 import static com.oracle.graal.hotspot.meta.HotSpotResolvedObjectType.*;
-import static com.oracle.graal.phases.GraalOptions.*;
-import static java.lang.reflect.Modifier.*;
 
 import java.lang.annotation.*;
 import java.lang.reflect.*;
 import java.util.*;
 
 import com.oracle.graal.api.meta.*;
-import com.oracle.graal.graph.*;
+import com.oracle.graal.compiler.common.*;
 import com.oracle.graal.hotspot.*;
 import com.oracle.graal.options.*;
 import com.oracle.graal.replacements.*;
@@ -174,8 +173,6 @@
 
                 fields.add(metaAccess.lookupJavaField(Throwable.class.getDeclaredField("UNASSIGNED_STACK")));
                 fields.add(metaAccess.lookupJavaField(Throwable.class.getDeclaredField("SUPPRESSED_SENTINEL")));
-
-                fields.add(metaAccess.lookupJavaField(NodeClass.class.getDeclaredField("registry")));
             } catch (SecurityException | NoSuchFieldException e) {
                 throw new GraalInternalError(e);
             }
@@ -202,8 +199,8 @@
         assert !ImmutableCode.getValue() || isCalledForSnippets() : receiver;
 
         if (receiver == null) {
-            assert isStatic(modifiers);
-            if (Modifier.isFinal(getModifiers())) {
+            assert isStatic();
+            if (isFinal()) {
                 if (holder.isInitialized() && !holder.getName().equals(SystemClassName) && isEmbeddable()) {
                     return readValue(receiver);
                 }
@@ -213,14 +210,14 @@
              * for non-static final fields, we must assume that they are only initialized if they
              * have a non-default value.
              */
-            assert !isStatic(modifiers);
+            assert !isStatic();
             Object object = HotSpotObjectConstant.asObject(receiver);
 
             // Canonicalization may attempt to process an unsafe read before
             // processing a guard (e.g. a null check or a type check) for this read
             // so we need to check the object being read
             if (object != null && isInObject(object)) {
-                if (Modifier.isFinal(getModifiers())) {
+                if (isFinal()) {
                     Constant value = readValue(receiver);
                     if (assumeNonStaticFinalFieldsAsFinal(object.getClass()) || !value.isDefaultForKind()) {
                         return value;
@@ -250,7 +247,7 @@
      *         {@code object}'s class
      */
     public boolean isInObject(Object object) {
-        if (isStatic(modifiers)) {
+        if (isStatic()) {
             return false;
         }
         return getDeclaringClass().isAssignableFrom(HotSpotResolvedObjectType.fromClass(object.getClass()));
@@ -259,13 +256,13 @@
     @Override
     public Constant readValue(Constant receiver) {
         if (receiver == null) {
-            assert isStatic(modifiers);
+            assert isStatic();
             if (holder.isInitialized()) {
                 return runtime().getHostProviders().getConstantReflection().readUnsafeConstant(getKind(), HotSpotObjectConstant.forObject(holder.mirror()), offset);
             }
             return null;
         } else {
-            assert !isStatic(modifiers);
+            assert !isStatic();
             assert receiver.isNonNull() && isInObject(HotSpotObjectConstant.asObject(receiver));
             return runtime().getHostProviders().getConstantReflection().readUnsafeConstant(getKind(), receiver, offset);
         }
diff -r 3dde8d8c95b8 -r 40d0022115ee 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	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotResolvedJavaMethod.java	Mon Apr 28 11:18:15 2014 +0200
@@ -22,18 +22,19 @@
  */
 package com.oracle.graal.hotspot.meta;
 
-import static com.oracle.graal.graph.UnsafeAccess.*;
+import static com.oracle.graal.compiler.common.GraalOptions.*;
+import static com.oracle.graal.compiler.common.UnsafeAccess.*;
 import static com.oracle.graal.hotspot.HotSpotGraalRuntime.*;
-import static com.oracle.graal.phases.GraalOptions.*;
 
 import java.lang.annotation.*;
 import java.lang.reflect.*;
+import java.util.*;
 
 import com.oracle.graal.api.code.*;
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.api.meta.ProfilingInfo.TriState;
+import com.oracle.graal.compiler.common.*;
 import com.oracle.graal.debug.*;
-import com.oracle.graal.graph.*;
 import com.oracle.graal.hotspot.*;
 import com.oracle.graal.hotspot.debug.*;
 import com.oracle.graal.nodes.*;
@@ -55,7 +56,6 @@
     private final HotSpotSignature signature;
     private HotSpotMethodData methodData;
     private byte[] code;
-    private SpeculationLog speculationLog;
 
     /**
      * Gets the holder of a HotSpot metaspace method native object.
@@ -162,6 +162,10 @@
         return HotSpotMetaspaceConstant.forMetaspaceObject(getHostWordKind(), metaspaceMethod, this);
     }
 
+    public long getMetaspaceMethod() {
+        return metaspaceMethod;
+    }
+
     @Override
     public Constant getEncoding() {
         return getMetaspaceMethodConstant();
@@ -182,8 +186,7 @@
 
     @Override
     public boolean canBeStaticallyBound() {
-        int modifiers = getModifiers();
-        return (Modifier.isFinal(modifiers) || Modifier.isPrivate(modifiers) || Modifier.isStatic(modifiers)) && !Modifier.isAbstract(modifiers);
+        return (isFinal() || isPrivate() || isStatic() || holder.isFinal()) && !isAbstract();
     }
 
     @Override
@@ -310,18 +313,17 @@
 
     @Override
     public boolean isClassInitializer() {
-        return "".equals(name) && Modifier.isStatic(getModifiers());
+        return "".equals(name) && isStatic();
     }
 
     @Override
     public boolean isConstructor() {
-        return "".equals(name) && !Modifier.isStatic(getModifiers());
+        return "".equals(name) && !isStatic();
     }
 
     @Override
     public int getMaxLocals() {
-        int modifiers = getModifiers();
-        if (Modifier.isAbstract(modifiers) || Modifier.isNative(modifiers)) {
+        if (isAbstract() || isNative()) {
             return 0;
         }
         HotSpotVMConfig config = runtime().getConfig();
@@ -330,8 +332,7 @@
 
     @Override
     public int getMaxStackSize() {
-        int modifiers = getModifiers();
-        if (Modifier.isAbstract(modifiers) || Modifier.isNative(modifiers)) {
+        if (isAbstract() || isNative()) {
             return 0;
         }
         HotSpotVMConfig config = runtime().getConfig();
@@ -612,15 +613,40 @@
      * @return virtual table index
      */
     private int getVtableIndex() {
+        assert !holder.isInterface();
         HotSpotVMConfig config = runtime().getConfig();
-        return unsafe.getInt(metaspaceMethod + config.methodVtableIndexOffset);
+        int result = unsafe.getInt(metaspaceMethod + config.methodVtableIndexOffset);
+        assert result >= config.nonvirtualVtableIndex : "must be linked";
+        return result;
     }
 
+    /**
+     * The {@link SpeculationLog} for methods compiled by Graal hang off this per-declaring-type
+     * {@link ClassValue}. The raw Method* value is safe to use as a key in the map as a) it is
+     * never moves and b) we never read from it.
+     * 

+ * One implication is that we will preserve {@link SpeculationLog}s for methods that have been + * redefined via class redefinition. It's tempting to periodically flush such logs but we cannot + * read the JVM_ACC_IS_OBSOLETE bit (or anything else) via the raw pointer as obsoleted methods + * are subject to clean up and deletion (see InstanceKlass::purge_previous_versions_internal). + */ + private static final ClassValue> SpeculationLogs = new ClassValue>() { + @Override + protected Map computeValue(java.lang.Class type) { + return new HashMap<>(4); + } + }; + public SpeculationLog getSpeculationLog() { - if (speculationLog == null) { - speculationLog = new HotSpotSpeculationLog(); + Map map = SpeculationLogs.get(holder.mirror()); + synchronized (map) { + SpeculationLog log = map.get(this.metaspaceMethod); + if (log == null) { + log = new HotSpotSpeculationLog(); + map.put(metaspaceMethod, log); + } + return log; } - return speculationLog; } public int intrinsicId() { diff -r 3dde8d8c95b8 -r 40d0022115ee 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 Fri Apr 25 16:21:07 2014 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotResolvedObjectType.java Mon Apr 28 11:18:15 2014 +0200 @@ -23,17 +23,15 @@ package com.oracle.graal.hotspot.meta; import static com.oracle.graal.api.meta.MetaUtil.*; -import static com.oracle.graal.graph.UnsafeAccess.*; +import static com.oracle.graal.compiler.common.UnsafeAccess.*; import static com.oracle.graal.hotspot.HotSpotGraalRuntime.*; -import static java.lang.reflect.Modifier.*; - import java.lang.annotation.*; import java.lang.reflect.*; import java.net.*; import java.util.*; import com.oracle.graal.api.meta.*; -import com.oracle.graal.graph.*; +import com.oracle.graal.compiler.common.*; import com.oracle.graal.hotspot.*; /** @@ -141,7 +139,7 @@ public ResolvedJavaType findUniqueConcreteSubtype() { HotSpotVMConfig config = runtime().getConfig(); if (isArray()) { - return isFinal(getElementalType(this).getModifiers()) ? this : null; + return getElementalType(this).isFinal() ? this : null; } else if (isInterface()) { final long implementorMetaspaceKlass = runtime().getCompilerToVM().getKlassImplementor(metaspaceKlass()); @@ -157,20 +155,20 @@ * than one implementors (see: InstanceKlass::add_implementor). The isInterface check * takes care of this fact since this class is an interface. */ - if (isAbstract(type.getModifiers()) || type.isInterface() || !type.isLeafClass()) { + if (type.isAbstract() || type.isInterface() || !type.isLeafClass()) { return null; } return type; } else { HotSpotResolvedObjectType type = this; - while (isAbstract(type.getModifiers())) { + while (type.isAbstract()) { long subklass = type.getSubklass(); if (subklass == 0 || unsafeReadWord(subklass + config.nextSiblingOffset) != 0) { return null; } type = (HotSpotResolvedObjectType) fromMetaspaceKlass(subklass); } - if (isAbstract(type.getModifiers()) || type.isInterface() || !type.isLeafClass()) { + if (type.isAbstract() || type.isInterface() || !type.isLeafClass()) { return null; } return type; @@ -255,7 +253,7 @@ if (isArray()) { return getComponentType().asExactType() != null ? this : null; } - return isFinal(getModifiers()) ? this : null; + return isFinal() ? this : null; } @Override @@ -358,7 +356,7 @@ @Override public ResolvedJavaMethod resolveMethod(ResolvedJavaMethod method) { assert method instanceof HotSpotMethod; - if (!isAbstract(method.getModifiers()) && method.getDeclaringClass().equals(this)) { + if (!method.isAbstract() && method.getDeclaringClass().equals(this)) { return method; } @@ -367,7 +365,7 @@ return null; } HotSpotResolvedJavaMethod resolvedMethod = HotSpotResolvedJavaMethod.fromMetaspace(resolvedMetaspaceMethod); - if (isAbstract(resolvedMethod.getModifiers())) { + if (resolvedMethod.isAbstract()) { return null; } return resolvedMethod; diff -r 3dde8d8c95b8 -r 40d0022115ee 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 Fri Apr 25 16:21:07 2014 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotResolvedPrimitiveType.java Mon Apr 28 11:18:15 2014 +0200 @@ -27,7 +27,7 @@ import java.net.*; import com.oracle.graal.api.meta.*; -import com.oracle.graal.graph.*; +import com.oracle.graal.compiler.common.*; /** * Implementation of {@link JavaType} for primitive HotSpot types. diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotRuntimeStub.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotRuntimeStub.java Fri Apr 25 16:21:07 2014 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotRuntimeStub.java Mon Apr 28 11:18:15 2014 +0200 @@ -24,7 +24,7 @@ import com.oracle.graal.api.code.*; import com.oracle.graal.api.meta.*; -import com.oracle.graal.graph.*; +import com.oracle.graal.compiler.common.*; import com.oracle.graal.hotspot.stubs.*; /** @@ -32,8 +32,6 @@ */ public class HotSpotRuntimeStub extends HotSpotInstalledCode { - private static final long serialVersionUID = -6388648408298441748L; - private final Stub stub; public HotSpotRuntimeStub(Stub stub) { @@ -44,18 +42,21 @@ return null; } + @Override public boolean isValid() { return true; } + @Override public void invalidate() { } @Override public String toString() { - return String.format("InstalledRuntimeStub[stub=%s, codeBlob=0x%x]", stub, getCodeBlob()); + return String.format("InstalledRuntimeStub[stub=%s, codeBlob=0x%x]", stub, getAddress()); } + @Override public Object executeVarargs(Object... args) throws InvalidInstalledCodeException { throw new GraalInternalError("Cannot call stub %s", stub); } diff -r 3dde8d8c95b8 -r 40d0022115ee 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 Fri Apr 25 16:21:07 2014 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotSignature.java Mon Apr 28 11:18:15 2014 +0200 @@ -27,7 +27,7 @@ import java.util.*; import com.oracle.graal.api.meta.*; -import com.oracle.graal.graph.*; +import com.oracle.graal.compiler.common.*; import com.oracle.graal.hotspot.*; import com.oracle.graal.java.*; diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotSuitesProvider.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotSuitesProvider.java Fri Apr 25 16:21:07 2014 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotSuitesProvider.java Mon Apr 28 11:18:15 2014 +0200 @@ -22,7 +22,7 @@ */ package com.oracle.graal.hotspot.meta; -import static com.oracle.graal.phases.GraalOptions.*; +import static com.oracle.graal.compiler.common.GraalOptions.*; import com.oracle.graal.hotspot.*; import com.oracle.graal.hotspot.phases.*; diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nfi/HotSpotNativeFunctionHandle.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nfi/HotSpotNativeFunctionHandle.java Fri Apr 25 16:21:07 2014 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nfi/HotSpotNativeFunctionHandle.java Mon Apr 28 11:18:15 2014 +0200 @@ -26,9 +26,9 @@ import com.oracle.graal.api.code.*; import com.oracle.graal.api.meta.*; +import com.oracle.graal.compiler.common.*; import com.oracle.graal.debug.*; import com.oracle.graal.debug.Debug.Scope; -import com.oracle.graal.graph.*; public class HotSpotNativeFunctionHandle implements NativeFunctionHandle { @@ -63,7 +63,7 @@ assert checkArgs(args); try { traceCall(args); - Object res = code.executeVarargs(args); + Object res = code.executeVarargs(args, null, null); traceResult(res); return res; } catch (InvalidInstalledCodeException e) { diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nfi/HotSpotNativeFunctionInterface.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nfi/HotSpotNativeFunctionInterface.java Fri Apr 25 16:21:07 2014 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nfi/HotSpotNativeFunctionInterface.java Mon Apr 28 11:18:15 2014 +0200 @@ -23,7 +23,7 @@ package com.oracle.graal.hotspot.nfi; import static com.oracle.graal.api.code.CodeUtil.*; -import static com.oracle.graal.graph.UnsafeAccess.*; +import static com.oracle.graal.compiler.common.UnsafeAccess.*; import static com.oracle.graal.hotspot.nfi.NativeCallStubGraphBuilder.*; import com.oracle.graal.api.code.*; @@ -161,7 +161,7 @@ DefaultProfilingInfo.get(TriState.UNKNOWN), null, suites, new CompilationResult(), CompilationResultBuilderFactory.Default); InstalledCode installedCode; try (Scope s = Debug.scope("CodeInstall", providers.getCodeCache(), g.method())) { - installedCode = providers.getCodeCache().addMethod(g.method(), compResult, null); + installedCode = providers.getCodeCache().addMethod(g.method(), compResult, null, null); } return installedCode; } diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nfi/NativeCallStubGraphBuilder.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nfi/NativeCallStubGraphBuilder.java Fri Apr 25 16:21:07 2014 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nfi/NativeCallStubGraphBuilder.java Mon Apr 28 11:18:15 2014 +0200 @@ -27,12 +27,12 @@ import java.util.*; import com.oracle.graal.api.meta.*; -import com.oracle.graal.graph.*; +import com.oracle.graal.compiler.common.*; +import com.oracle.graal.compiler.common.type.*; import com.oracle.graal.hotspot.meta.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.extended.*; import com.oracle.graal.nodes.java.*; -import com.oracle.graal.nodes.type.*; import com.oracle.graal.nodes.virtual.*; import com.oracle.graal.word.phases.*; diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/AllocaNode.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/AllocaNode.java Fri Apr 25 16:21:07 2014 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/AllocaNode.java Mon Apr 28 11:18:15 2014 +0200 @@ -26,18 +26,16 @@ import com.oracle.graal.api.code.*; import com.oracle.graal.api.meta.*; -import com.oracle.graal.compiler.gen.*; -import com.oracle.graal.compiler.target.*; +import com.oracle.graal.compiler.common.type.*; import com.oracle.graal.hotspot.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.spi.*; -import com.oracle.graal.nodes.type.*; /** * Reserves a block of memory in the stack frame of a method. The block is reserved in the frame for * the entire execution of the associated method. */ -public final class AllocaNode extends FixedWithNextNode implements LIRGenResLowerable { +public final class AllocaNode extends FixedWithNextNode implements LIRLowerable { /** * The number of slots in block. @@ -58,8 +56,8 @@ } @Override - public void generate(NodeLIRBuilderTool gen, LIRGenerationResult res) { - StackSlot array = res.getFrameMap().allocateStackSlots(slots, objects, null); + public void generate(NodeLIRBuilderTool gen) { + StackSlot array = gen.getLIRGeneratorTool().getResult().getFrameMap().allocateStackSlots(slots, objects, null); Value result = gen.getLIRGeneratorTool().emitAddress(array); gen.setResult(this, result); } diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/BeginLockScopeNode.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/BeginLockScopeNode.java Fri Apr 25 16:21:07 2014 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/BeginLockScopeNode.java Mon Apr 28 11:18:15 2014 +0200 @@ -24,12 +24,11 @@ import com.oracle.graal.api.code.*; import com.oracle.graal.api.meta.*; -import com.oracle.graal.compiler.gen.*; -import com.oracle.graal.compiler.target.*; import com.oracle.graal.graph.*; import com.oracle.graal.hotspot.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.extended.*; +import com.oracle.graal.nodes.spi.*; import com.oracle.graal.word.*; /** @@ -39,7 +38,7 @@ * check on the object. */ @NodeInfo(allowedUsageTypes = {InputType.Memory}) -public final class BeginLockScopeNode extends AbstractMemoryCheckpoint implements LIRGenLowerable, MonitorEnter, MemoryCheckpoint.Single { +public final class BeginLockScopeNode extends AbstractMemoryCheckpoint implements LIRLowerable, MonitorEnter, MemoryCheckpoint.Single { private int lockDepth; @@ -59,7 +58,7 @@ } @Override - public void generate(NodeLIRBuilder gen) { + public void generate(NodeLIRBuilderTool gen) { assert lockDepth != -1; HotSpotLIRGenerator hsGen = (HotSpotLIRGenerator) gen.getLIRGeneratorTool(); StackSlot slot = hsGen.getLockSlot(lockDepth); diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/CStringNode.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/CStringNode.java Fri Apr 25 16:21:07 2014 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/CStringNode.java Mon Apr 28 11:18:15 2014 +0200 @@ -23,8 +23,6 @@ package com.oracle.graal.hotspot.nodes; import com.oracle.graal.api.meta.*; -import com.oracle.graal.compiler.gen.*; -import com.oracle.graal.compiler.target.*; import com.oracle.graal.nodes.calc.*; import com.oracle.graal.nodes.spi.*; import com.oracle.graal.word.*; @@ -32,7 +30,7 @@ /** * Converts a compile-time constant Java string into a C string installed with the generated code. */ -public final class CStringNode extends FloatingNode implements LIRGenLowerable { +public final class CStringNode extends FloatingNode implements LIRLowerable { private final String string; @@ -41,7 +39,7 @@ this.string = string; } - public void generate(NodeLIRBuilder gen) { + public void generate(NodeLIRBuilderTool gen) { gen.setResult(this, emitCString(gen, string)); } diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/CompressionNode.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/CompressionNode.java Fri Apr 25 16:21:07 2014 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/CompressionNode.java Mon Apr 28 11:18:15 2014 +0200 @@ -23,6 +23,8 @@ package com.oracle.graal.hotspot.nodes; import com.oracle.graal.api.meta.*; +import com.oracle.graal.compiler.common.*; +import com.oracle.graal.compiler.common.type.*; import com.oracle.graal.graph.*; import com.oracle.graal.graph.spi.*; import com.oracle.graal.hotspot.*; @@ -73,7 +75,7 @@ } else if (input instanceof IntegerStamp) { // compressed metaspace pointer assert PrimitiveStamp.getBits(input) == 64; - return StampFactory.forInteger(32, false); + return StampFactory.forInteger(32); } break; case Uncompress: @@ -84,13 +86,17 @@ } else if (input instanceof IntegerStamp) { // metaspace pointer assert PrimitiveStamp.getBits(input) == 32; - return StampFactory.forInteger(64, false); + return StampFactory.forInteger(64); } break; } throw GraalInternalError.shouldNotReachHere(); } + public ValueNode getInput() { + return input; + } + @Override public Node canonical(CanonicalizerTool tool) { if (input instanceof CompressionNode) { @@ -107,7 +113,7 @@ HotSpotLIRGenerator hsGen = (HotSpotLIRGenerator) gen.getLIRGeneratorTool(); boolean nonNull; if (input.stamp() instanceof ObjectStamp) { - nonNull = ObjectStamp.isObjectNonNull(input.stamp()); + nonNull = StampTool.isObjectNonNull(input.stamp()); } else { // metaspace pointers are never null nonNull = true; diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/CurrentJavaThreadNode.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/CurrentJavaThreadNode.java Fri Apr 25 16:21:07 2014 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/CurrentJavaThreadNode.java Mon Apr 28 11:18:15 2014 +0200 @@ -26,11 +26,11 @@ import com.oracle.graal.api.code.*; import com.oracle.graal.api.meta.*; -import com.oracle.graal.graph.*; +import com.oracle.graal.compiler.common.*; +import com.oracle.graal.compiler.common.type.*; import com.oracle.graal.hotspot.*; import com.oracle.graal.nodes.calc.*; import com.oracle.graal.nodes.spi.*; -import com.oracle.graal.nodes.type.*; import com.oracle.graal.word.*; /** diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/DeoptimizeCallerNode.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/DeoptimizeCallerNode.java Fri Apr 25 16:21:07 2014 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/DeoptimizeCallerNode.java Mon Apr 28 11:18:15 2014 +0200 @@ -23,11 +23,11 @@ package com.oracle.graal.hotspot.nodes; import com.oracle.graal.api.meta.*; +import com.oracle.graal.compiler.common.type.*; import com.oracle.graal.graph.*; import com.oracle.graal.hotspot.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.spi.*; -import com.oracle.graal.nodes.type.*; /** * Removes the current frame and tail calls the uncommon trap routine. diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/DeoptimizingStubCall.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/DeoptimizingStubCall.java Fri Apr 25 16:21:07 2014 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/DeoptimizingStubCall.java Mon Apr 28 11:18:15 2014 +0200 @@ -22,8 +22,8 @@ */ package com.oracle.graal.hotspot.nodes; +import com.oracle.graal.compiler.common.type.*; import com.oracle.graal.nodes.*; -import com.oracle.graal.nodes.type.*; public class DeoptimizingStubCall extends DeoptimizingFixedWithNextNode { diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/DimensionsNode.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/DimensionsNode.java Fri Apr 25 16:21:07 2014 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/DimensionsNode.java Mon Apr 28 11:18:15 2014 +0200 @@ -28,8 +28,7 @@ import com.oracle.graal.api.code.*; import com.oracle.graal.api.meta.*; -import com.oracle.graal.compiler.gen.*; -import com.oracle.graal.compiler.target.*; +import com.oracle.graal.lir.gen.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.spi.*; import com.oracle.graal.word.*; @@ -38,7 +37,7 @@ * Intrinsic for allocating an on-stack array of integers to hold the dimensions of a multianewarray * instruction. */ -public final class DimensionsNode extends FixedWithNextNode implements LIRGenResLowerable { +public final class DimensionsNode extends FixedWithNextNode implements LIRLowerable { private final int rank; @@ -48,12 +47,13 @@ } @Override - public void generate(NodeLIRBuilderTool gen, LIRGenerationResult res) { + public void generate(NodeLIRBuilderTool gen) { + LIRGeneratorTool lirGen = gen.getLIRGeneratorTool(); int size = rank * 4; - int wordSize = gen.getLIRGeneratorTool().target().wordSize; + int wordSize = lirGen.target().wordSize; int slots = roundUp(size, wordSize) / wordSize; - StackSlot array = res.getFrameMap().allocateStackSlots(slots, new BitSet(0), null); - Value result = gen.getLIRGeneratorTool().emitAddress(array); + StackSlot array = lirGen.getResult().getFrameMap().allocateStackSlots(slots, new BitSet(0), null); + Value result = lirGen.emitAddress(array); gen.setResult(this, result); } diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/DirectCompareAndSwapNode.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/DirectCompareAndSwapNode.java Fri Apr 25 16:21:07 2014 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/DirectCompareAndSwapNode.java Mon Apr 28 11:18:15 2014 +0200 @@ -23,13 +23,12 @@ package com.oracle.graal.hotspot.nodes; 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.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.extended.*; import com.oracle.graal.nodes.java.*; +import com.oracle.graal.nodes.spi.*; import com.oracle.graal.word.*; /** @@ -39,7 +38,7 @@ * expected value or the compared against value instead of a boolean. */ @NodeInfo(allowedUsageTypes = {InputType.Memory}) -public class DirectCompareAndSwapNode extends FixedWithNextNode implements LIRGenLowerable, MemoryCheckpoint.Single { +public class DirectCompareAndSwapNode extends FixedWithNextNode implements LIRLowerable, MemoryCheckpoint.Single { @Input private ValueNode object; @Input private ValueNode offset; @@ -79,7 +78,7 @@ } @Override - public void generate(NodeLIRBuilder gen) { + public void generate(NodeLIRBuilderTool gen) { ((HotSpotNodeLIRBuilder) gen).visitDirectCompareAndSwap(this); } diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/EndLockScopeNode.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/EndLockScopeNode.java Fri Apr 25 16:21:07 2014 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/EndLockScopeNode.java Mon Apr 28 11:18:15 2014 +0200 @@ -23,11 +23,11 @@ package com.oracle.graal.hotspot.nodes; import com.oracle.graal.api.meta.*; +import com.oracle.graal.compiler.common.type.*; import com.oracle.graal.graph.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.extended.*; import com.oracle.graal.nodes.spi.*; -import com.oracle.graal.nodes.type.*; /** * Intrinsic for closing a {@linkplain BeginLockScopeNode scope} binding a stack-based lock with an diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/EnterUnpackFramesStackFrameNode.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/EnterUnpackFramesStackFrameNode.java Mon Apr 28 11:18:15 2014 +0200 @@ -0,0 +1,60 @@ +/* + * Copyright (c) 2013, 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.graal.hotspot.nodes; + +import com.oracle.graal.api.meta.*; +import com.oracle.graal.compiler.common.type.*; +import com.oracle.graal.hotspot.*; +import com.oracle.graal.hotspot.stubs.*; +import com.oracle.graal.nodes.*; +import com.oracle.graal.nodes.spi.*; +import com.oracle.graal.word.*; + +/** + * Emits code to enter a low-level stack frame specifically to call out to the C++ method + * {@link DeoptimizationStub#UNPACK_FRAMES Deoptimization::unpack_frames}. + */ +public class EnterUnpackFramesStackFrameNode extends FixedWithNextNode implements LIRLowerable { + + @Input private ValueNode framePc; + @Input private ValueNode senderSp; + @Input private ValueNode senderFp; + + public EnterUnpackFramesStackFrameNode(ValueNode framePc, ValueNode senderSp, ValueNode senderFp) { + super(StampFactory.forVoid()); + this.framePc = framePc; + this.senderSp = senderSp; + this.senderFp = senderFp; + } + + @Override + public void generate(NodeLIRBuilderTool gen) { + Value operandValue = gen.operand(framePc); + Value senderSpValue = gen.operand(senderSp); + Value senderFpValue = gen.operand(senderFp); + ((HotSpotLIRGenerator) gen.getLIRGeneratorTool()).emitEnterUnpackFramesStackFrame(operandValue, senderSpValue, senderFpValue); + } + + @NodeIntrinsic + public static native void enterUnpackFramesStackFrame(Word framePc, Word senderSp, Word senderFp); +} diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/GetObjectAddressNode.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/GetObjectAddressNode.java Fri Apr 25 16:21:07 2014 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/GetObjectAddressNode.java Mon Apr 28 11:18:15 2014 +0200 @@ -23,9 +23,9 @@ package com.oracle.graal.hotspot.nodes; import com.oracle.graal.api.meta.*; +import com.oracle.graal.compiler.common.type.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.spi.*; -import com.oracle.graal.nodes.type.*; /** * Intrinsification for getting the address of an object. The code path(s) between a call to diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/HotSpotDirectCallTargetNode.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/HotSpotDirectCallTargetNode.java Fri Apr 25 16:21:07 2014 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/HotSpotDirectCallTargetNode.java Mon Apr 28 11:18:15 2014 +0200 @@ -26,9 +26,9 @@ import com.oracle.graal.api.code.CallingConvention.Type; import com.oracle.graal.api.meta.*; +import com.oracle.graal.compiler.common.type.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.java.MethodCallTargetNode.InvokeKind; -import com.oracle.graal.nodes.type.*; public class HotSpotDirectCallTargetNode extends DirectCallTargetNode { diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/HotSpotIndirectCallTargetNode.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/HotSpotIndirectCallTargetNode.java Fri Apr 25 16:21:07 2014 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/HotSpotIndirectCallTargetNode.java Mon Apr 28 11:18:15 2014 +0200 @@ -26,8 +26,8 @@ import com.oracle.graal.api.code.CallingConvention.Type; import com.oracle.graal.api.meta.*; +import com.oracle.graal.compiler.common.type.*; import com.oracle.graal.nodes.*; -import com.oracle.graal.nodes.type.*; public class HotSpotIndirectCallTargetNode extends IndirectCallTargetNode { diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/HotSpotMatchableNodes.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/HotSpotMatchableNodes.java Mon Apr 28 11:18:15 2014 +0200 @@ -0,0 +1,37 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.graal.hotspot.nodes; + +import com.oracle.graal.compiler.match.*; +import com.oracle.graal.nodes.*; + +@MatchableNode(shortName = "Compression", value = CompressionNode.class, inputs = 1, adapter = HotSpotMatchableNodes.CompressionNodeAdapter.class) +public class HotSpotMatchableNodes { + public static class CompressionNodeAdapter extends MatchNodeAdapter { + @Override + protected ValueNode getFirstInput(ValueNode node) { + return ((CompressionNode) node).getInput(); + } + } + +} diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/JumpToExceptionHandlerInCallerNode.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/JumpToExceptionHandlerInCallerNode.java Fri Apr 25 16:21:07 2014 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/JumpToExceptionHandlerInCallerNode.java Mon Apr 28 11:18:15 2014 +0200 @@ -22,10 +22,10 @@ */ package com.oracle.graal.hotspot.nodes; +import com.oracle.graal.compiler.common.type.*; import com.oracle.graal.hotspot.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.spi.*; -import com.oracle.graal.nodes.type.*; import com.oracle.graal.word.*; /** diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/LeaveCurrentStackFrameNode.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/LeaveCurrentStackFrameNode.java Mon Apr 28 11:18:15 2014 +0200 @@ -0,0 +1,47 @@ +/* + * Copyright (c) 2013, 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.graal.hotspot.nodes; + +import com.oracle.graal.compiler.common.type.*; +import com.oracle.graal.hotspot.*; +import com.oracle.graal.nodes.*; +import com.oracle.graal.nodes.spi.*; + +/** + * Emits code to leave (pop) the current low-level stack frame. This operation also removes the + * return address if its location is on the stack. + */ +public class LeaveCurrentStackFrameNode extends FixedWithNextNode implements LIRLowerable { + + public LeaveCurrentStackFrameNode() { + super(StampFactory.forVoid()); + } + + @Override + public void generate(NodeLIRBuilderTool gen) { + ((HotSpotLIRGenerator) gen.getLIRGeneratorTool()).emitLeaveCurrentStackFrame(); + } + + @NodeIntrinsic + public static native void leaveCurrentStackFrame(); +} diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/LeaveDeoptimizedStackFrameNode.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/LeaveDeoptimizedStackFrameNode.java Mon Apr 28 11:18:15 2014 +0200 @@ -0,0 +1,57 @@ +/* + * Copyright (c) 2013, 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.graal.hotspot.nodes; + +import com.oracle.graal.api.meta.*; +import com.oracle.graal.compiler.common.type.*; +import com.oracle.graal.hotspot.*; +import com.oracle.graal.hotspot.stubs.*; +import com.oracle.graal.nodes.*; +import com.oracle.graal.nodes.spi.*; +import com.oracle.graal.word.*; + +/** + * Emits code to leave (pop) the current low-level stack frame which is being deoptimized. This node + * is only used in {@link DeoptimizationStub}. + */ +public class LeaveDeoptimizedStackFrameNode extends FixedWithNextNode implements LIRLowerable { + + @Input private ValueNode frameSize; + @Input private ValueNode initialInfo; + + public LeaveDeoptimizedStackFrameNode(ValueNode frameSize, ValueNode initialInfo) { + super(StampFactory.forVoid()); + this.frameSize = frameSize; + this.initialInfo = initialInfo; + } + + @Override + public void generate(NodeLIRBuilderTool gen) { + Value frameSizeValue = gen.operand(frameSize); + Value initialInfoValue = gen.operand(initialInfo); + ((HotSpotLIRGenerator) gen.getLIRGeneratorTool()).emitLeaveDeoptimizedStackFrame(frameSizeValue, initialInfoValue); + } + + @NodeIntrinsic + public static native void leaveDeoptimizedStackFrame(int frameSize, Word initialInfo); +} diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/LeaveUnpackFramesStackFrameNode.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/LeaveUnpackFramesStackFrameNode.java Mon Apr 28 11:18:15 2014 +0200 @@ -0,0 +1,48 @@ +/* + * Copyright (c) 2013, 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.graal.hotspot.nodes; + +import com.oracle.graal.compiler.common.type.*; +import com.oracle.graal.hotspot.*; +import com.oracle.graal.hotspot.stubs.*; +import com.oracle.graal.nodes.*; +import com.oracle.graal.nodes.spi.*; + +/** + * Emits code to leave a low-level stack frame specifically to call out to the C++ method + * {@link DeoptimizationStub#UNPACK_FRAMES Deoptimization::unpack_frames}. + */ +public class LeaveUnpackFramesStackFrameNode extends FixedWithNextNode implements LIRLowerable { + + public LeaveUnpackFramesStackFrameNode() { + super(StampFactory.forVoid()); + } + + @Override + public void generate(NodeLIRBuilderTool gen) { + ((HotSpotLIRGenerator) gen.getLIRGeneratorTool()).emitLeaveUnpackFramesStackFrame(); + } + + @NodeIntrinsic + public static native void leaveUnpackFramesStackFrame(); +} diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/LoadExceptionObjectNode.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/LoadExceptionObjectNode.java Mon Apr 28 11:18:15 2014 +0200 @@ -0,0 +1,39 @@ +/* + * Copyright (c) 2009, 2011, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.graal.hotspot.nodes; + +import com.oracle.graal.compiler.common.type.*; +import com.oracle.graal.nodes.*; +import com.oracle.graal.nodes.spi.*; + +public class LoadExceptionObjectNode extends AbstractStateSplit implements Lowerable { + + public LoadExceptionObjectNode(Stamp stamp) { + super(stamp); + } + + @Override + public void lower(LoweringTool tool) { + tool.getLowerer().lower(this, tool); + } +} diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/MonitorCounterNode.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/MonitorCounterNode.java Fri Apr 25 16:21:07 2014 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/MonitorCounterNode.java Mon Apr 28 11:18:15 2014 +0200 @@ -26,8 +26,6 @@ import com.oracle.graal.api.code.*; import com.oracle.graal.api.meta.*; -import com.oracle.graal.compiler.gen.*; -import com.oracle.graal.compiler.target.*; import com.oracle.graal.nodes.calc.*; import com.oracle.graal.nodes.spi.*; import com.oracle.graal.word.*; @@ -35,16 +33,16 @@ /** * Node that is used to maintain a stack based counter of how many locks are currently held. */ -public final class MonitorCounterNode extends FloatingNode implements LIRGenResLowerable { +public final class MonitorCounterNode extends FloatingNode implements LIRLowerable { private MonitorCounterNode() { super(null); } @Override - public void generate(NodeLIRBuilderTool gen, LIRGenerationResult res) { + public void generate(NodeLIRBuilderTool gen) { assert graph().getNodes().filter(MonitorCounterNode.class).count() == 1 : "monitor counters not canonicalized to single instance"; - StackSlot counter = res.getFrameMap().allocateStackSlots(1, new BitSet(0), null); + StackSlot counter = gen.getLIRGeneratorTool().getResult().getFrameMap().allocateStackSlots(1, new BitSet(0), null); Value result = gen.getLIRGeneratorTool().emitAddress(counter); gen.setResult(this, result); } diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/NewArrayStubCall.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/NewArrayStubCall.java Fri Apr 25 16:21:07 2014 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/NewArrayStubCall.java Mon Apr 28 11:18:15 2014 +0200 @@ -24,19 +24,18 @@ import com.oracle.graal.api.code.*; import com.oracle.graal.api.meta.*; -import com.oracle.graal.compiler.gen.*; -import com.oracle.graal.compiler.target.*; +import com.oracle.graal.compiler.common.type.*; import com.oracle.graal.hotspot.meta.*; import com.oracle.graal.hotspot.stubs.*; import com.oracle.graal.lir.*; import com.oracle.graal.nodes.*; -import com.oracle.graal.nodes.type.*; +import com.oracle.graal.nodes.spi.*; import com.oracle.graal.word.*; /** * A call to the {@link NewArrayStub}. */ -public class NewArrayStubCall extends DeoptimizingStubCall implements LIRGenLowerable { +public class NewArrayStubCall extends DeoptimizingStubCall implements LIRLowerable { private static final Stamp defaultStamp = StampFactory.objectNonNull(); @@ -61,9 +60,9 @@ } @Override - public void generate(NodeLIRBuilder gen) { + public void generate(NodeLIRBuilderTool gen) { ForeignCallLinkage linkage = gen.getLIRGeneratorTool().getForeignCalls().lookupForeignCall(NEW_ARRAY); - Variable result = gen.getLIRGenerator().emitForeignCall(linkage, this, gen.operand(hub), gen.operand(length)); + Variable result = gen.getLIRGeneratorTool().emitForeignCall(linkage, gen.state(this), gen.operand(hub), gen.operand(length)); gen.setResult(this, result); } diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/NewInstanceStubCall.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/NewInstanceStubCall.java Fri Apr 25 16:21:07 2014 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/NewInstanceStubCall.java Mon Apr 28 11:18:15 2014 +0200 @@ -24,11 +24,11 @@ import com.oracle.graal.api.code.*; import com.oracle.graal.api.meta.*; +import com.oracle.graal.compiler.common.type.*; import com.oracle.graal.hotspot.meta.*; import com.oracle.graal.hotspot.stubs.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.spi.*; -import com.oracle.graal.nodes.type.*; import com.oracle.graal.word.*; /** @@ -59,7 +59,7 @@ @Override public void generate(NodeLIRBuilderTool gen) { ForeignCallLinkage linkage = gen.getLIRGeneratorTool().getForeignCalls().lookupForeignCall(NEW_INSTANCE); - Value result = gen.getLIRGeneratorTool().emitForeignCall(linkage, this, gen.operand(hub)); + Value result = gen.getLIRGeneratorTool().emitForeignCall(linkage, gen.state(this), gen.operand(hub)); gen.setResult(this, result); } diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/NewMultiArrayStubCall.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/NewMultiArrayStubCall.java Fri Apr 25 16:21:07 2014 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/NewMultiArrayStubCall.java Mon Apr 28 11:18:15 2014 +0200 @@ -24,11 +24,11 @@ import com.oracle.graal.api.code.*; import com.oracle.graal.api.meta.*; +import com.oracle.graal.compiler.common.type.*; import com.oracle.graal.hotspot.meta.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.extended.*; import com.oracle.graal.nodes.spi.*; -import com.oracle.graal.nodes.type.*; import com.oracle.graal.word.*; /** diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/PatchReturnAddressNode.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/PatchReturnAddressNode.java Fri Apr 25 16:21:07 2014 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/PatchReturnAddressNode.java Mon Apr 28 11:18:15 2014 +0200 @@ -22,10 +22,10 @@ */ package com.oracle.graal.hotspot.nodes; +import com.oracle.graal.compiler.common.type.*; import com.oracle.graal.hotspot.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.spi.*; -import com.oracle.graal.nodes.type.*; import com.oracle.graal.word.*; /** diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/PrefetchAllocateNode.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/PrefetchAllocateNode.java Fri Apr 25 16:21:07 2014 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/PrefetchAllocateNode.java Mon Apr 28 11:18:15 2014 +0200 @@ -23,14 +23,13 @@ package com.oracle.graal.hotspot.nodes; -import com.oracle.graal.compiler.gen.*; -import com.oracle.graal.compiler.target.*; +import com.oracle.graal.compiler.common.type.*; import com.oracle.graal.hotspot.*; import com.oracle.graal.nodes.*; -import com.oracle.graal.nodes.type.*; +import com.oracle.graal.nodes.spi.*; import com.oracle.graal.word.*; -public class PrefetchAllocateNode extends FixedWithNextNode implements LIRGenLowerable { +public class PrefetchAllocateNode extends FixedWithNextNode implements LIRLowerable { @Input private ValueNode distance; @Input private ValueNode address; @@ -42,7 +41,7 @@ } @Override - public void generate(NodeLIRBuilder gen) { + public void generate(NodeLIRBuilderTool gen) { ((HotSpotNodeLIRBuilder) gen).emitPrefetchAllocate(address, distance); } diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/PushInterpreterFrameNode.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/PushInterpreterFrameNode.java Mon Apr 28 11:18:15 2014 +0200 @@ -0,0 +1,62 @@ +/* + * Copyright (c) 2013, 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.graal.hotspot.nodes; + +import com.oracle.graal.api.meta.*; +import com.oracle.graal.compiler.common.type.*; +import com.oracle.graal.hotspot.*; +import com.oracle.graal.nodes.*; +import com.oracle.graal.nodes.spi.*; +import com.oracle.graal.word.*; + +/** + * A call to the runtime code implementing the uncommon trap logic. + */ +public class PushInterpreterFrameNode extends FixedWithNextNode implements LIRLowerable { + + @Input private ValueNode framePc; + @Input private ValueNode frameSize; + @Input private ValueNode senderSp; + @Input private ValueNode initialInfo; + + public PushInterpreterFrameNode(ValueNode frameSize, ValueNode framePc, ValueNode senderSp, ValueNode initialInfo) { + super(StampFactory.forVoid()); + this.frameSize = frameSize; + this.framePc = framePc; + this.senderSp = senderSp; + this.initialInfo = initialInfo; + } + + @Override + public void generate(NodeLIRBuilderTool gen) { + Value frameSizeValue = gen.operand(frameSize); + Value framePcValue = gen.operand(framePc); + Value senderSpValue = gen.operand(senderSp); + Value initialInfoValue = gen.operand(initialInfo); + ((HotSpotLIRGenerator) gen.getLIRGeneratorTool()).emitPushInterpreterFrame(frameSizeValue, framePcValue, senderSpValue, initialInfoValue); + } + + @NodeIntrinsic + public static native void pushInterpreterFrame(Word frameSize, Word framePc, Word senderSp, Word initialInfo); + +} diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/SaveAllRegistersNode.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/SaveAllRegistersNode.java Mon Apr 28 11:18:15 2014 +0200 @@ -0,0 +1,62 @@ +/* + * Copyright (c) 2013, 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.graal.hotspot.nodes; + +import com.oracle.graal.api.meta.*; +import com.oracle.graal.compiler.common.type.*; +import com.oracle.graal.hotspot.*; +import com.oracle.graal.lir.StandardOp.*; +import com.oracle.graal.nodes.*; +import com.oracle.graal.nodes.spi.*; + +/** + * Saves all allocatable registers. + */ +public class SaveAllRegistersNode extends FixedWithNextNode implements LIRLowerable { + + private SaveRegistersOp saveRegistersOp; + + public SaveAllRegistersNode() { + super(StampFactory.forKind(Kind.Long)); + } + + @Override + public void generate(NodeLIRBuilderTool gen) { + saveRegistersOp = ((HotSpotLIRGenerator) gen.getLIRGeneratorTool()).emitSaveAllRegisters(); + } + + /** + * @return the map from registers to the stack locations in they are saved + */ + public SaveRegistersOp getSaveRegistersOp() { + assert saveRegistersOp != null : "saved registers op has not yet been created"; + return saveRegistersOp; + } + + /** + * @return a token that couples this node to an {@link UncommonTrapCallNode} so that the latter + * has access to the {@linkplain SaveRegistersOp#getMap register save map} + */ + @NodeIntrinsic + public static native long saveAllRegisters(); +} diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/SnippetAnchorNode.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/SnippetAnchorNode.java Fri Apr 25 16:21:07 2014 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/SnippetAnchorNode.java Mon Apr 28 11:18:15 2014 +0200 @@ -22,11 +22,11 @@ */ package com.oracle.graal.hotspot.nodes; +import com.oracle.graal.compiler.common.type.*; import com.oracle.graal.graph.*; import com.oracle.graal.graph.spi.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.extended.*; -import com.oracle.graal.nodes.type.*; @NodeInfo(allowedUsageTypes = {InputType.Value, InputType.Anchor, InputType.Guard}) public final class SnippetAnchorNode extends FixedWithNextNode implements Simplifiable, GuardingNode { @@ -37,7 +37,7 @@ @Override public void simplify(SimplifierTool tool) { - AbstractBeginNode prevBegin = BeginNode.prevBegin(this); + BeginNode prevBegin = BeginNode.prevBegin(this); replaceAtUsages(InputType.Anchor, prevBegin); replaceAtUsages(InputType.Guard, prevBegin); if (usages().isEmpty()) { diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/SnippetLocationProxyNode.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/SnippetLocationProxyNode.java Fri Apr 25 16:21:07 2014 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/SnippetLocationProxyNode.java Mon Apr 28 11:18:15 2014 +0200 @@ -22,12 +22,12 @@ */ package com.oracle.graal.hotspot.nodes; +import com.oracle.graal.compiler.common.type.*; import com.oracle.graal.graph.*; import com.oracle.graal.graph.spi.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.calc.*; import com.oracle.graal.nodes.extended.*; -import com.oracle.graal.nodes.type.*; @NodeInfo(allowedUsageTypes = {InputType.Association, InputType.Value}) public final class SnippetLocationProxyNode extends FloatingNode implements Canonicalizable { diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/StubForeignCallNode.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/StubForeignCallNode.java Fri Apr 25 16:21:07 2014 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/StubForeignCallNode.java Mon Apr 28 11:18:15 2014 +0200 @@ -24,11 +24,11 @@ import com.oracle.graal.api.code.*; import com.oracle.graal.api.meta.*; +import com.oracle.graal.compiler.common.type.*; import com.oracle.graal.graph.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.extended.*; import com.oracle.graal.nodes.spi.*; -import com.oracle.graal.nodes.type.*; /** * Node for a {@linkplain ForeignCallDescriptor foreign} call from within a stub. @@ -68,7 +68,7 @@ @Override public void generate(NodeLIRBuilderTool gen) { assert graph().start() instanceof StubStartNode; - ForeignCallLinkage linkage = gen.getLIRGeneratorTool().getForeignCalls().lookupForeignCall(descriptor); + ForeignCallLinkage linkage = foreignCalls.lookupForeignCall(descriptor); Value[] operands = operands(gen); Value result = gen.getLIRGeneratorTool().emitForeignCall(linkage, null, operands); if (result != null) { diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/TailcallNode.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/TailcallNode.java Fri Apr 25 16:21:07 2014 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/TailcallNode.java Mon Apr 28 11:18:15 2014 +0200 @@ -24,25 +24,23 @@ import static com.oracle.graal.hotspot.HotSpotGraalRuntime.*; -import java.lang.reflect.*; import java.util.*; import com.oracle.graal.api.code.*; import com.oracle.graal.api.meta.*; -import com.oracle.graal.compiler.gen.*; -import com.oracle.graal.compiler.target.*; +import com.oracle.graal.compiler.common.type.*; import com.oracle.graal.graph.*; import com.oracle.graal.hotspot.*; import com.oracle.graal.java.*; +import com.oracle.graal.lir.gen.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.spi.*; -import com.oracle.graal.nodes.type.*; /** * Performs a tail call to the specified target compiled method, with the parameter taken from the * supplied FrameState. */ -public class TailcallNode extends FixedWithNextNode implements LIRGenResLowerable { +public class TailcallNode extends FixedWithNextNode implements LIRLowerable { @Input(InputType.State) private FrameState frameState; @Input private ValueNode target; @@ -59,20 +57,21 @@ this.frameState = frameState; } - public void generate(NodeLIRBuilderTool gen, LIRGenerationResult res) { + public void generate(NodeLIRBuilderTool gen) { HotSpotVMConfig config = runtime().getConfig(); + LIRGeneratorTool lirGen = gen.getLIRGeneratorTool(); ResolvedJavaMethod method = frameState.method(); - boolean isStatic = Modifier.isStatic(method.getModifiers()); + boolean isStatic = method.isStatic(); JavaType[] signature = MetaUtil.signatureToTypes(method.getSignature(), isStatic ? null : method.getDeclaringClass()); - CallingConvention cc = res.getFrameMap().registerConfig.getCallingConvention(CallingConvention.Type.JavaCall, null, signature, gen.getLIRGeneratorTool().target(), false); + CallingConvention cc = lirGen.getResult().getFrameMap().registerConfig.getCallingConvention(CallingConvention.Type.JavaCall, null, signature, lirGen.target(), false); List parameters = new ArrayList<>(); for (int i = 0, slot = 0; i < cc.getArgumentCount(); i++, slot += HIRFrameStateBuilder.stackSlots(frameState.localAt(slot).getKind())) { parameters.add(frameState.localAt(slot)); } Value[] args = gen.visitInvokeArguments(cc, parameters); - Value address = gen.getLIRGeneratorTool().emitAddress(gen.operand(target), config.nmethodEntryOffset, Value.ILLEGAL, 0); - Value entry = gen.getLIRGeneratorTool().emitLoad(Kind.Long, address, null); + Value address = lirGen.emitAddress(gen.operand(target), config.nmethodEntryOffset, Value.ILLEGAL, 0); + Value entry = lirGen.emitLoad(Kind.Long, address, null); HotSpotLIRGenerator hsgen = (HotSpotLIRGenerator) gen; hsgen.emitTailcall(args, entry); } diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/UncommonTrapCallNode.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/UncommonTrapCallNode.java Mon Apr 28 11:18:15 2014 +0200 @@ -0,0 +1,80 @@ +/* + * Copyright (c) 2013, 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.graal.hotspot.nodes; + +import com.oracle.graal.api.code.*; +import com.oracle.graal.api.meta.*; +import com.oracle.graal.compiler.common.type.*; +import com.oracle.graal.graph.*; +import com.oracle.graal.hotspot.*; +import com.oracle.graal.lir.StandardOp.SaveRegistersOp; +import com.oracle.graal.nodes.*; +import com.oracle.graal.nodes.extended.*; +import com.oracle.graal.nodes.spi.*; +import com.oracle.graal.word.*; + +/** + * A call to the runtime code implementing the uncommon trap logic. + */ +@NodeInfo(allowedUsageTypes = {InputType.Memory}) +public class UncommonTrapCallNode extends FixedWithNextNode implements LIRLowerable, MemoryCheckpoint.Multi { + + @Input private ValueNode trapRequest; + @Input private SaveAllRegistersNode registerSaver; + private final ForeignCallsProvider foreignCalls; + public static final ForeignCallDescriptor UNCOMMON_TRAP = new ForeignCallDescriptor("uncommonTrap", Word.class, Word.class, int.class); + + public UncommonTrapCallNode(@InjectedNodeParameter ForeignCallsProvider foreignCalls, ValueNode registerSaver, ValueNode trapRequest) { + super(StampFactory.forKind(Kind.fromJavaClass(UNCOMMON_TRAP.getResultType()))); + this.trapRequest = trapRequest; + this.registerSaver = (SaveAllRegistersNode) registerSaver; + this.foreignCalls = foreignCalls; + } + + @Override + public LocationIdentity[] getLocationIdentities() { + return foreignCalls.getKilledLocations(UNCOMMON_TRAP); + } + + public SaveRegistersOp getSaveRegistersOp() { + return registerSaver.getSaveRegistersOp(); + } + + @Override + public void generate(NodeLIRBuilderTool gen) { + Value trapRequestValue = gen.operand(trapRequest); + Value result = ((HotSpotLIRGenerator) gen.getLIRGeneratorTool()).emitUncommonTrapCall(trapRequestValue, getSaveRegistersOp()); + gen.setResult(this, result); + } + + @NodeIntrinsic + public static native Word uncommonTrap(long registerSaver, int trapRequest); + + public MemoryCheckpoint asMemoryCheckpoint() { + return null; + } + + public MemoryPhiNode asMemoryPhi() { + return null; + } +} diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/VMErrorNode.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/VMErrorNode.java Fri Apr 25 16:21:07 2014 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/VMErrorNode.java Mon Apr 28 11:18:15 2014 +0200 @@ -27,9 +27,9 @@ import com.oracle.graal.api.code.*; import com.oracle.graal.api.meta.*; +import com.oracle.graal.compiler.common.type.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.spi.*; -import com.oracle.graal.nodes.type.*; import com.oracle.graal.replacements.*; /** diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/WriteBarrier.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/WriteBarrier.java Fri Apr 25 16:21:07 2014 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/WriteBarrier.java Mon Apr 28 11:18:15 2014 +0200 @@ -22,11 +22,11 @@ */ package com.oracle.graal.hotspot.nodes; +import com.oracle.graal.compiler.common.type.*; import com.oracle.graal.graph.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.extended.*; import com.oracle.graal.nodes.spi.*; -import com.oracle.graal.nodes.type.*; public abstract class WriteBarrier extends FixedWithNextNode implements Lowerable { diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/type/NarrowOopStamp.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/type/NarrowOopStamp.java Fri Apr 25 16:21:07 2014 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/type/NarrowOopStamp.java Mon Apr 28 11:18:15 2014 +0200 @@ -23,9 +23,9 @@ package com.oracle.graal.hotspot.nodes.type; import com.oracle.graal.api.meta.*; +import com.oracle.graal.compiler.common.spi.*; +import com.oracle.graal.compiler.common.type.*; import com.oracle.graal.hotspot.HotSpotVMConfig.CompressEncoding; -import com.oracle.graal.nodes.spi.*; -import com.oracle.graal.nodes.type.*; public class NarrowOopStamp extends ObjectStamp { @@ -76,7 +76,7 @@ } @Override - public PlatformKind getPlatformKind(LIRTypeTool tool) { + public PlatformKind getPlatformKind(PlatformKindTool tool) { return NarrowOop; } diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/phases/AheadOfTimeVerificationPhase.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/phases/AheadOfTimeVerificationPhase.java Fri Apr 25 16:21:07 2014 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/phases/AheadOfTimeVerificationPhase.java Mon Apr 28 11:18:15 2014 +0200 @@ -27,6 +27,7 @@ import com.oracle.graal.api.meta.*; import com.oracle.graal.hotspot.meta.*; import com.oracle.graal.nodes.*; +import com.oracle.graal.nodes.type.*; import com.oracle.graal.phases.*; import com.oracle.graal.phases.tiers.*; @@ -45,7 +46,7 @@ protected boolean verify(StructuredGraph graph, PhaseContext context) { for (ConstantNode node : getConstantNodes(graph)) { if (node.recordsUsages() || !node.gatherUsages(graph).isEmpty()) { - if (isObject(node) && !isNullReference(node) && !isInternedString(node)) { + if (isObject(node) && !isNullReference(node) && !isInternedString(node) && !isDirectMethodHandle(node)) { throw new VerificationError("illegal object constant: " + node); } } @@ -61,6 +62,13 @@ return isObject(node) && node.asConstant().isNull(); } + private static boolean isDirectMethodHandle(ConstantNode node) { + if (!isObject(node)) { + return false; + } + return "Ljava/lang/invoke/DirectMethodHandle;".equals(StampTool.typeOrNull(node).getName()); + } + @SuppressFBWarnings(value = "ES_COMPARING_STRINGS_WITH_EQ", justification = "reference equality is what we want") private static boolean isInternedString(ConstantNode node) { if (!isObject(node)) { diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/phases/LoadJavaMirrorWithKlassPhase.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/phases/LoadJavaMirrorWithKlassPhase.java Fri Apr 25 16:21:07 2014 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/phases/LoadJavaMirrorWithKlassPhase.java Mon Apr 28 11:18:15 2014 +0200 @@ -26,10 +26,10 @@ import static com.oracle.graal.nodes.ConstantNode.*; import com.oracle.graal.api.meta.*; +import com.oracle.graal.compiler.common.type.*; import com.oracle.graal.hotspot.meta.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.extended.*; -import com.oracle.graal.nodes.type.*; import com.oracle.graal.phases.*; import com.oracle.graal.phases.common.*; import com.oracle.graal.phases.tiers.*; diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/phases/OnStackReplacementPhase.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/phases/OnStackReplacementPhase.java Fri Apr 25 16:21:07 2014 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/phases/OnStackReplacementPhase.java Mon Apr 28 11:18:15 2014 +0200 @@ -23,6 +23,7 @@ package com.oracle.graal.hotspot.phases; import com.oracle.graal.api.code.*; +import com.oracle.graal.compiler.common.*; import com.oracle.graal.debug.*; import com.oracle.graal.graph.*; import com.oracle.graal.graph.Node.Verbosity; diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/phases/WriteBarrierAdditionPhase.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/phases/WriteBarrierAdditionPhase.java Fri Apr 25 16:21:07 2014 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/phases/WriteBarrierAdditionPhase.java Mon Apr 28 11:18:15 2014 +0200 @@ -75,12 +75,12 @@ } protected void addG1PostWriteBarrier(FixedAccessNode node, ValueNode object, ValueNode value, LocationNode location, boolean precise, StructuredGraph graph) { - final boolean alwaysNull = ObjectStamp.isObjectAlwaysNull(value); + final boolean alwaysNull = StampTool.isObjectAlwaysNull(value); graph.addAfterFixed(node, graph.add(new G1PostWriteBarrier(object, value, location, precise, alwaysNull))); } protected void addSerialPostWriteBarrier(FixedAccessNode node, ValueNode object, ValueNode value, LocationNode location, boolean precise, StructuredGraph graph) { - final boolean alwaysNull = ObjectStamp.isObjectAlwaysNull(value); + final boolean alwaysNull = StampTool.isObjectAlwaysNull(value); final LocationNode loc = (precise ? location : null); graph.addAfterFixed(node, graph.add(new SerialWriteBarrier(object, loc, precise, alwaysNull))); } diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/AESCryptSubstitutions.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/AESCryptSubstitutions.java Fri Apr 25 16:21:07 2014 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/AESCryptSubstitutions.java Mon Apr 28 11:18:15 2014 +0200 @@ -27,7 +27,7 @@ import com.oracle.graal.api.meta.*; import com.oracle.graal.api.replacements.*; -import com.oracle.graal.graph.*; +import com.oracle.graal.compiler.common.*; import com.oracle.graal.graph.Node.ConstantNodeParameter; import com.oracle.graal.graph.Node.NodeIntrinsic; import com.oracle.graal.hotspot.*; diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/AbstractMethodHandleNode.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/AbstractMethodHandleNode.java Fri Apr 25 16:21:07 2014 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/AbstractMethodHandleNode.java Mon Apr 28 11:18:15 2014 +0200 @@ -22,10 +22,11 @@ */ package com.oracle.graal.hotspot.replacements; -import java.lang.reflect.*; import java.util.*; import com.oracle.graal.api.meta.*; +import com.oracle.graal.compiler.common.*; +import com.oracle.graal.compiler.common.type.*; import com.oracle.graal.graph.*; import com.oracle.graal.graph.spi.*; import com.oracle.graal.hotspot.meta.*; @@ -52,7 +53,7 @@ /** * Search for an instance field with the given name in a class. - * + * * @param className name of the class to search in * @param fieldName name of the field to be searched * @return resolved java field @@ -99,7 +100,7 @@ /** * Get the receiver of a MethodHandle.invokeBasic call. - * + * * @return the receiver argument node */ private ValueNode getReceiver() { @@ -108,7 +109,7 @@ /** * Get the MemberName argument of a MethodHandle.linkTo* call. - * + * * @return the MemberName argument node (which is the last argument) */ private ValueNode getMemberName() { @@ -118,7 +119,7 @@ /** * Used from {@link MethodHandleInvokeBasicNode} to get the target {@link InvokeNode} if the * method handle receiver is constant. - * + * * @return invoke node for the {@link java.lang.invoke.MethodHandle} target */ protected InvokeNode getInvokeBasicTarget() { @@ -137,7 +138,7 @@ * Used from {@link MethodHandleLinkToStaticNode}, {@link MethodHandleLinkToSpecialNode}, * {@link MethodHandleLinkToVirtualNode}, and {@link MethodHandleLinkToInterfaceNode} to get the * target {@link InvokeNode} if the member name argument is constant. - * + * * @return invoke node for the member name target */ protected InvokeNode getLinkToTarget() { @@ -152,7 +153,7 @@ /** * Helper function to get the {@link InvokeNode} for the vmtarget of a * java.lang.invoke.MemberName. - * + * * @param memberName constant member name node * @return invoke node for the member name target */ @@ -171,7 +172,7 @@ // to a direct call we must cast the receiver and arguments to its // actual types. HotSpotSignature signature = targetMethod.getSignature(); - final boolean isStatic = Modifier.isStatic(targetMethod.getModifiers()); + final boolean isStatic = targetMethod.isStatic(); final int receiverSkip = isStatic ? 0 : 1; // Cast receiver to its type. @@ -188,7 +189,7 @@ // Try to get the most accurate receiver type if (this instanceof MethodHandleLinkToVirtualNode || this instanceof MethodHandleLinkToInterfaceNode) { - ResolvedJavaType receiverType = ObjectStamp.typeOrNull(getReceiver().stamp()); + ResolvedJavaType receiverType = StampTool.typeOrNull(getReceiver().stamp()); if (receiverType != null) { ResolvedJavaMethod concreteMethod = receiverType.findUniqueConcreteMethod(targetMethod); if (concreteMethod != null) { @@ -212,7 +213,7 @@ /** * Inserts a node to cast the argument at index to the given type if the given type is more * concrete than the argument type. - * + * * @param index of the argument to be cast * @param type the type the argument should be cast to */ @@ -221,7 +222,7 @@ ResolvedJavaType targetType = (ResolvedJavaType) type; if (!targetType.isPrimitive()) { ValueNode argument = arguments.get(index); - ResolvedJavaType argumentType = ObjectStamp.typeOrNull(argument.stamp()); + ResolvedJavaType argumentType = StampTool.typeOrNull(argument.stamp()); if (argumentType == null || (argumentType.isAssignableFrom(targetType) && !argumentType.equals(targetType))) { PiNode piNode = graph().unique(new PiNode(argument, StampFactory.declared(targetType))); arguments.set(index, piNode); @@ -233,12 +234,12 @@ /** * Creates an {@link InvokeNode} for the given target method. The {@link CallTargetNode} passed * to the InvokeNode is in fact a {@link SelfReplacingMethodCallTargetNode}. - * + * * @param targetMethod the method the be called * @return invoke node for the member name target */ private InvokeNode createTargetInvokeNode(ResolvedJavaMethod targetMethod) { - InvokeKind invokeKind = Modifier.isStatic(targetMethod.getModifiers()) ? InvokeKind.Static : InvokeKind.Special; + InvokeKind invokeKind = targetMethod.isStatic() ? InvokeKind.Static : InvokeKind.Special; JavaType returnType = targetMethod.getSignature().getReturnType(null); // MethodHandleLinkTo* nodes have a trailing MemberName argument which diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/ArrayCopyCallNode.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/ArrayCopyCallNode.java Fri Apr 25 16:21:07 2014 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/ArrayCopyCallNode.java Mon Apr 28 11:18:15 2014 +0200 @@ -27,6 +27,8 @@ import com.oracle.graal.api.meta.*; import com.oracle.graal.api.runtime.*; +import com.oracle.graal.compiler.common.*; +import com.oracle.graal.compiler.common.type.*; import com.oracle.graal.graph.*; import com.oracle.graal.hotspot.meta.*; import com.oracle.graal.hotspot.nodes.*; @@ -34,8 +36,6 @@ import com.oracle.graal.nodes.calc.*; import com.oracle.graal.nodes.extended.*; import com.oracle.graal.nodes.spi.*; -import com.oracle.graal.nodes.type.*; -import com.oracle.graal.phases.*; import com.oracle.graal.replacements.SnippetTemplate.Arguments; import com.oracle.graal.runtime.*; diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/ArrayCopyNode.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/ArrayCopyNode.java Fri Apr 25 16:21:07 2014 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/ArrayCopyNode.java Mon Apr 28 11:18:15 2014 +0200 @@ -26,6 +26,7 @@ import static com.oracle.graal.hotspot.replacements.HotSpotReplacementsUtil.*; import com.oracle.graal.api.meta.*; +import com.oracle.graal.compiler.common.*; import com.oracle.graal.debug.*; import com.oracle.graal.debug.Debug.Scope; import com.oracle.graal.loop.phases.*; @@ -33,7 +34,6 @@ import com.oracle.graal.nodes.spi.*; import com.oracle.graal.nodes.type.*; import com.oracle.graal.nodes.virtual.*; -import com.oracle.graal.phases.*; import com.oracle.graal.phases.common.*; import com.oracle.graal.phases.tiers.*; import com.oracle.graal.replacements.nodes.*; @@ -69,8 +69,8 @@ } private StructuredGraph selectSnippet(LoweringTool tool, final Replacements replacements) { - ResolvedJavaType srcType = ObjectStamp.typeOrNull(getSource().stamp()); - ResolvedJavaType destType = ObjectStamp.typeOrNull(getDestination().stamp()); + ResolvedJavaType srcType = StampTool.typeOrNull(getSource().stamp()); + ResolvedJavaType destType = StampTool.typeOrNull(getDestination().stamp()); if (srcType == null || !srcType.isArray() || destType == null || !destType.isArray()) { return null; @@ -143,13 +143,13 @@ * Returns true if this copy doesn't require store checks. Trivially true for primitive arrays. */ private boolean isExact() { - ResolvedJavaType srcType = ObjectStamp.typeOrNull(getSource().stamp()); + ResolvedJavaType srcType = StampTool.typeOrNull(getSource().stamp()); if (srcType.getComponentType().getKind().isPrimitive() || getSource() == getDestination()) { return true; } - ResolvedJavaType destType = ObjectStamp.typeOrNull(getDestination().stamp()); - if (ObjectStamp.isExactType(getDestination().stamp())) { + ResolvedJavaType destType = StampTool.typeOrNull(getDestination().stamp()); + if (StampTool.isExactType(getDestination().stamp())) { if (destType != null && destType.isAssignableFrom(srcType)) { return true; } @@ -171,10 +171,10 @@ if (state.getState() == EscapeState.Virtual) { type = state.getVirtualObject().type(); } else { - type = ObjectStamp.typeOrNull(state.getMaterializedValue()); + type = StampTool.typeOrNull(state.getMaterializedValue()); } } else { - type = ObjectStamp.typeOrNull(entry); + type = StampTool.typeOrNull(entry); } if (type == null || !destComponentType.isAssignableFrom(type)) { return false; diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/ArrayCopySnippets.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/ArrayCopySnippets.java Fri Apr 25 16:21:07 2014 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/ArrayCopySnippets.java Mon Apr 28 11:18:15 2014 +0200 @@ -22,16 +22,16 @@ */ package com.oracle.graal.hotspot.replacements; +import static com.oracle.graal.compiler.common.GraalOptions.*; import static com.oracle.graal.hotspot.replacements.HotSpotReplacementsUtil.*; import static com.oracle.graal.nodes.GuardingPiNode.*; import static com.oracle.graal.nodes.extended.BranchProbabilityNode.*; -import static com.oracle.graal.phases.GraalOptions.*; import java.lang.reflect.*; import java.util.*; import com.oracle.graal.api.meta.*; -import com.oracle.graal.graph.*; +import com.oracle.graal.compiler.common.*; import com.oracle.graal.graph.Node.ConstantNodeParameter; import com.oracle.graal.graph.Node.NodeIntrinsic; import com.oracle.graal.nodes.*; diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/CallSiteSubstitutions.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/CallSiteSubstitutions.java Fri Apr 25 16:21:07 2014 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/CallSiteSubstitutions.java Mon Apr 28 11:18:15 2014 +0200 @@ -34,7 +34,7 @@ public class CallSiteSubstitutions implements ReplacementsProvider { @Override - public void registerReplacements(MetaAccessProvider metaAccess, LoweringProvider loweringProvider, Replacements replacements, TargetDescription target) { + public void registerReplacements(MetaAccessProvider metaAccess, LoweringProvider loweringProvider, SnippetReflectionProvider snippetReflection, Replacements replacements, TargetDescription target) { replacements.registerSubstitutions(ConstantCallSiteSubstitutions.class); replacements.registerSubstitutions(MutableCallSiteSubstitutions.class); replacements.registerSubstitutions(VolatileCallSiteSubstitutions.class); diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/CheckCastDynamicSnippets.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/CheckCastDynamicSnippets.java Fri Apr 25 16:21:07 2014 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/CheckCastDynamicSnippets.java Mon Apr 28 11:18:15 2014 +0200 @@ -31,6 +31,7 @@ import static com.oracle.graal.replacements.SnippetTemplate.*; import com.oracle.graal.api.code.*; +import com.oracle.graal.compiler.common.type.*; import com.oracle.graal.debug.*; import com.oracle.graal.hotspot.meta.*; import com.oracle.graal.hotspot.nodes.*; @@ -38,7 +39,6 @@ import com.oracle.graal.nodes.extended.*; import com.oracle.graal.nodes.java.*; import com.oracle.graal.nodes.spi.*; -import com.oracle.graal.nodes.type.*; import com.oracle.graal.replacements.*; import com.oracle.graal.replacements.SnippetTemplate.AbstractTemplates; import com.oracle.graal.replacements.SnippetTemplate.Arguments; diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/CipherBlockChainingSubstitutions.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/CipherBlockChainingSubstitutions.java Fri Apr 25 16:21:07 2014 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/CipherBlockChainingSubstitutions.java Mon Apr 28 11:18:15 2014 +0200 @@ -27,7 +27,7 @@ import com.oracle.graal.api.meta.*; import com.oracle.graal.api.replacements.*; -import com.oracle.graal.graph.*; +import com.oracle.graal.compiler.common.*; import com.oracle.graal.graph.Node.ConstantNodeParameter; import com.oracle.graal.graph.Node.NodeIntrinsic; import com.oracle.graal.hotspot.nodes.*; diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/CompositeValueClassSubstitutions.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/CompositeValueClassSubstitutions.java Fri Apr 25 16:21:07 2014 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/CompositeValueClassSubstitutions.java Mon Apr 28 11:18:15 2014 +0200 @@ -22,7 +22,7 @@ */ package com.oracle.graal.hotspot.replacements; -import static com.oracle.graal.phases.GraalOptions.*; +import static com.oracle.graal.compiler.common.GraalOptions.*; import com.oracle.graal.api.meta.*; import com.oracle.graal.api.replacements.*; diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/HotSpotNodeClassSubstitutions.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/HotSpotNodeClassSubstitutions.java Fri Apr 25 16:21:07 2014 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/HotSpotNodeClassSubstitutions.java Mon Apr 28 11:18:15 2014 +0200 @@ -22,9 +22,7 @@ */ package com.oracle.graal.hotspot.replacements; -import static com.oracle.graal.hotspot.replacements.HotSpotReplacementsUtil.*; -import static com.oracle.graal.nodes.PiNode.*; -import static com.oracle.graal.phases.GraalOptions.*; +import static com.oracle.graal.compiler.common.GraalOptions.*; import com.oracle.graal.api.meta.*; import com.oracle.graal.api.replacements.*; @@ -33,7 +31,6 @@ import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.spi.*; import com.oracle.graal.replacements.nodes.*; -import com.oracle.graal.word.*; /** * Substitutions for improving the performance of {@link NodeClass#get}. @@ -61,15 +58,12 @@ } } + /** + * NOTE: A {@link MethodSubstitution} similar to + * {@link HotSpotNodeSubstitutions#getNodeClass(Node)} is not possible here because there is no + * guarantee that {@code c} is initialized (accessing a Class literal in Java is not a class + * initialization barrier). + */ @MacroSubstitution(isStatic = true, forced = true, macro = NodeClassGetNode.class) - @MethodSubstitution(isStatic = true) - public static NodeClass get(Class c) { - Word klass = loadWordFromObject(c, klassOffset()); - NodeClass nc = piCastExact(klass.readObject(Word.signed(klassNodeClassOffset()), KLASS_NODE_CLASS), NodeClass.class); - if (nc != null) { - return nc; - } - return get(c); - - } + public static native NodeClass get(Class c); } diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/HotSpotNodeSubstitutions.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/HotSpotNodeSubstitutions.java Fri Apr 25 16:21:07 2014 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/HotSpotNodeSubstitutions.java Mon Apr 28 11:18:15 2014 +0200 @@ -33,16 +33,15 @@ public class HotSpotNodeSubstitutions { /** - * Partial substitution of {@link Node#getNodeClass()} that returns the value of the - * {@code InstanceKlass::_graal_node_class} field if it is non-null. + * Gets the value of the {@code InstanceKlass::_graal_node_class} field from the InstanceKlass + * pointed to by {@code node}'s header. */ @MethodSubstitution(isStatic = false) - public static NodeClass getNodeClass(final Node thisObj) { - Word klass = loadHub(thisObj); - NodeClass nc = piCastExact(klass.readObject(Word.signed(klassNodeClassOffset()), KLASS_NODE_CLASS), NodeClass.class); - if (nc != null) { - return nc; - } - return getNodeClass(thisObj); + public static NodeClass getNodeClass(final Node node) { + // HotSpot creates the NodeClass for each Node subclass while initializing it + // so we are guaranteed to read a non-null value here. As long as NodeClass + // is final, the stamp of the PiNode below will automatically be exact. + Word klass = loadHub(node); + return piCastNonNull(klass.readObject(Word.signed(klassNodeClassOffset()), KLASS_NODE_CLASS), NodeClass.class); } } diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/HotSpotReplacementsUtil.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/HotSpotReplacementsUtil.java Fri Apr 25 16:21:07 2014 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/HotSpotReplacementsUtil.java Mon Apr 28 11:18:15 2014 +0200 @@ -22,7 +22,7 @@ */ package com.oracle.graal.hotspot.replacements; -import static com.oracle.graal.graph.UnsafeAccess.*; +import static com.oracle.graal.compiler.common.UnsafeAccess.*; import static com.oracle.graal.hotspot.HotSpotGraalRuntime.*; import static com.oracle.graal.hotspot.meta.HotSpotForeignCallsProviderImpl.*; import static com.oracle.graal.nodes.extended.BranchProbabilityNode.*; @@ -30,7 +30,7 @@ import com.oracle.graal.api.code.*; import com.oracle.graal.api.meta.*; -import com.oracle.graal.graph.*; +import com.oracle.graal.compiler.common.*; import com.oracle.graal.graph.Node.ConstantNodeParameter; import com.oracle.graal.graph.Node.NodeIntrinsic; import com.oracle.graal.hotspot.*; @@ -80,6 +80,20 @@ return config().threadExceptionPcOffset; } + public static final LocationIdentity LAST_JAVA_PC_LOCATION = new NamedLocationIdentity("LastJavaPc"); + + @Fold + public static int threadLastJavaPcOffset() { + return config().threadLastJavaPcOffset(); + } + + public static final LocationIdentity LAST_JAVA_FP_LOCATION = new NamedLocationIdentity("LastJavaFp"); + + @Fold + public static int threadLastJavaFpOffset() { + return config().threadLastJavaFpOffset(); + } + public static final LocationIdentity TLAB_TOP_LOCATION = new NamedLocationIdentity("TlabTop"); @Fold @@ -111,6 +125,16 @@ return config().pendingExceptionOffset; } + public static final LocationIdentity PENDING_DEOPTIMIZATION_LOCATION = new NamedLocationIdentity("PendingDeoptimization"); + + /** + * @see HotSpotVMConfig#pendingDeoptimizationOffset + */ + @Fold + private static int threadPendingDeoptimizationOffset() { + return config().pendingDeoptimizationOffset; + } + public static final LocationIdentity OBJECT_RESULT_LOCATION = new NamedLocationIdentity("ObjectResult"); @Fold @@ -140,6 +164,14 @@ thread.writeWord(threadExceptionPcOffset(), value, EXCEPTION_PC_LOCATION); } + public static void writeLastJavaPc(Word thread, Word value) { + thread.writeWord(threadLastJavaPcOffset(), value, LAST_JAVA_PC_LOCATION); + } + + public static void writeLastJavaFp(Word thread, Word value) { + thread.writeWord(threadLastJavaFpOffset(), value, LAST_JAVA_FP_LOCATION); + } + public static Word readTlabTop(Word thread) { return thread.readWord(threadTlabTopOffset(), TLAB_TOP_LOCATION); } @@ -174,6 +206,22 @@ } /** + * Reads the pending deoptimization value for the given thread. + * + * @return {@code true} if there was a pending deoptimization + */ + public static int readPendingDeoptimization(Word thread) { + return thread.readInt(threadPendingDeoptimizationOffset(), PENDING_DEOPTIMIZATION_LOCATION); + } + + /** + * Writes the pending deoptimization value for the given thread. + */ + public static void writePendingDeoptimization(Word thread, int value) { + thread.writeInt(threadPendingDeoptimizationOffset(), value, PENDING_DEOPTIMIZATION_LOCATION); + } + + /** * Gets and clears the object result from a runtime call stored in a thread local. * * @return the object that was in the thread local @@ -498,6 +546,9 @@ @NodeIntrinsic(value = ReadRegisterNode.class, setStampFromReturnType = true) public static native Word registerAsWord(@ConstantNodeParameter Register register, @ConstantNodeParameter boolean directUse, @ConstantNodeParameter boolean incoming); + @NodeIntrinsic(value = WriteRegisterNode.class, setStampFromReturnType = true) + public static native void writeRegisterAsWord(@ConstantNodeParameter Register register, Word value); + @SuppressWarnings("unused") @NodeIntrinsic(value = UnsafeLoadNode.class, setStampFromReturnType = true) private static Word loadWordFromObjectIntrinsic(Object object, long offset, @ConstantNodeParameter Kind wordKind, @ConstantNodeParameter LocationIdentity locationIdentity) { diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/HotSpotSubstitutions.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/HotSpotSubstitutions.java Fri Apr 25 16:21:07 2014 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/HotSpotSubstitutions.java Mon Apr 28 11:18:15 2014 +0200 @@ -24,6 +24,7 @@ import com.oracle.graal.api.code.*; import com.oracle.graal.api.meta.*; +import com.oracle.graal.api.replacements.*; import com.oracle.graal.api.runtime.*; import com.oracle.graal.nodes.spi.*; import com.oracle.graal.replacements.*; @@ -32,7 +33,7 @@ public class HotSpotSubstitutions implements ReplacementsProvider { @Override - public void registerReplacements(MetaAccessProvider metaAccess, LoweringProvider loweringProvider, Replacements replacements, TargetDescription target) { + public void registerReplacements(MetaAccessProvider metaAccess, LoweringProvider loweringProvider, SnippetReflectionProvider snippetReflection, Replacements replacements, TargetDescription target) { replacements.registerSubstitutions(ObjectSubstitutions.class); replacements.registerSubstitutions(SystemSubstitutions.class); replacements.registerSubstitutions(ThreadSubstitutions.class); diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/InstanceOfSnippets.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/InstanceOfSnippets.java Fri Apr 25 16:21:07 2014 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/InstanceOfSnippets.java Mon Apr 28 11:18:15 2014 +0200 @@ -33,6 +33,7 @@ import com.oracle.graal.api.code.*; import com.oracle.graal.api.meta.*; import com.oracle.graal.api.meta.ProfilingInfo.TriState; +import com.oracle.graal.compiler.common.type.*; import com.oracle.graal.hotspot.meta.*; import com.oracle.graal.hotspot.nodes.*; import com.oracle.graal.hotspot.replacements.TypeCheckSnippetUtils.Hints; @@ -40,7 +41,6 @@ import com.oracle.graal.nodes.extended.*; import com.oracle.graal.nodes.java.*; import com.oracle.graal.nodes.spi.*; -import com.oracle.graal.nodes.type.*; import com.oracle.graal.options.*; import com.oracle.graal.replacements.*; import com.oracle.graal.replacements.Snippet.ConstantParameter; diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/LoadExceptionObjectSnippets.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/LoadExceptionObjectSnippets.java Fri Apr 25 16:21:07 2014 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/LoadExceptionObjectSnippets.java Mon Apr 28 11:18:15 2014 +0200 @@ -28,12 +28,12 @@ import static com.oracle.graal.replacements.SnippetTemplate.*; import com.oracle.graal.api.code.*; +import com.oracle.graal.compiler.common.type.*; import com.oracle.graal.hotspot.meta.*; +import com.oracle.graal.hotspot.nodes.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.extended.*; -import com.oracle.graal.nodes.java.*; import com.oracle.graal.nodes.spi.*; -import com.oracle.graal.nodes.type.*; import com.oracle.graal.replacements.*; import com.oracle.graal.replacements.Snippet.ConstantParameter; import com.oracle.graal.replacements.SnippetTemplate.AbstractTemplates; @@ -44,6 +44,12 @@ /** * Snippet for loading the exception object at the start of an exception dispatcher. + *

+ * The frame state upon entry to an exception handler is such that it is a + * {@link BytecodeFrame#rethrowException rethrow exception} state and the stack contains exactly the + * exception object (per the JVM spec) to rethrow. This means that the code generated for this node + * must not cause a deoptimization as the runtime/interpreter would not have a valid location to + * find the exception object to be rethrown. */ public class LoadExceptionObjectSnippets implements Snippets { diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/MonitorSnippets.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/MonitorSnippets.java Fri Apr 25 16:21:07 2014 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/MonitorSnippets.java Mon Apr 28 11:18:15 2014 +0200 @@ -457,7 +457,7 @@ } static boolean isTracingEnabledForType(ValueNode object) { - ResolvedJavaType type = ObjectStamp.typeOrNull(object.stamp()); + ResolvedJavaType type = StampTool.typeOrNull(object.stamp()); if (TRACE_TYPE_FILTER == null) { return false; } else { @@ -511,7 +511,7 @@ callTarget = graph.add(new MethodCallTargetNode(InvokeKind.Static, checkCounter.getMethod(), new ValueNode[]{errMsg}, returnType)); invoke = graph.add(new InvokeNode(callTarget, 0)); List stack = Collections.emptyList(); - FrameState stateAfter = new FrameState(graph.method(), FrameState.AFTER_BCI, new ValueNode[0], stack, new ValueNode[0], new MonitorIdNode[0], false, false); + FrameState stateAfter = new FrameState(graph.method(), BytecodeFrame.AFTER_BCI, new ValueNode[0], stack, new ValueNode[0], new MonitorIdNode[0], false, false); invoke.setStateAfter(graph.add(stateAfter)); graph.addBeforeFixed(ret, invoke); diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/NewObjectSnippets.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/NewObjectSnippets.java Fri Apr 25 16:21:07 2014 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/NewObjectSnippets.java Mon Apr 28 11:18:15 2014 +0200 @@ -24,18 +24,19 @@ import static com.oracle.graal.api.code.UnsignedMath.*; import static com.oracle.graal.api.meta.MetaUtil.*; +import static com.oracle.graal.compiler.common.GraalOptions.*; import static com.oracle.graal.hotspot.replacements.HotSpotReplacementsUtil.*; import static com.oracle.graal.hotspot.replacements.NewObjectSnippets.Options.*; import static com.oracle.graal.nodes.PiArrayNode.*; import static com.oracle.graal.nodes.extended.BranchProbabilityNode.*; -import static com.oracle.graal.phases.GraalOptions.*; import static com.oracle.graal.replacements.SnippetTemplate.*; import static com.oracle.graal.replacements.nodes.ExplodeLoopNode.*; import com.oracle.graal.api.code.*; import com.oracle.graal.api.meta.*; +import com.oracle.graal.compiler.common.*; +import com.oracle.graal.compiler.common.type.*; import com.oracle.graal.debug.*; -import com.oracle.graal.graph.*; import com.oracle.graal.graph.Node.ConstantNodeParameter; import com.oracle.graal.graph.Node.NodeIntrinsic; import com.oracle.graal.hotspot.*; @@ -46,7 +47,6 @@ import com.oracle.graal.nodes.extended.*; import com.oracle.graal.nodes.java.*; import com.oracle.graal.nodes.spi.*; -import com.oracle.graal.nodes.type.*; import com.oracle.graal.options.*; import com.oracle.graal.replacements.*; import com.oracle.graal.replacements.Snippet.ConstantParameter; @@ -105,7 +105,7 @@ return ProfileAllocations.getValue(); } - private static void profileAllocation(String path, long size, String typeContext) { + protected static void profileAllocation(String path, long size, String typeContext) { if (doProfile()) { String name = createName(path, typeContext); @@ -347,7 +347,7 @@ /** * Formats some allocated memory with an object header and zeroes out the rest. */ - private static Object formatObject(Word hub, int size, Word memory, Word compileTimePrototypeMarkWord, boolean fillContents, boolean constantSize, boolean noAsserts, boolean useSnippetCounters) { + protected static Object formatObject(Word hub, int size, Word memory, Word compileTimePrototypeMarkWord, boolean fillContents, boolean constantSize, boolean noAsserts, boolean useSnippetCounters) { Word prototypeMarkWord = useBiasedLocking() ? hub.readWord(prototypeMarkWordOffset(), PROTOTYPE_MARK_WORD_LOCATION) : compileTimePrototypeMarkWord; initializeObjectHeader(memory, prototypeMarkWord, hub); if (fillContents) { diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/ObjectCloneNode.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/ObjectCloneNode.java Fri Apr 25 16:21:07 2014 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/ObjectCloneNode.java Mon Apr 28 11:18:15 2014 +0200 @@ -29,6 +29,7 @@ import com.oracle.graal.api.code.*; import com.oracle.graal.api.meta.*; +import com.oracle.graal.compiler.common.type.*; import com.oracle.graal.debug.*; import com.oracle.graal.debug.Debug.Scope; import com.oracle.graal.nodes.*; @@ -59,7 +60,7 @@ return null; } - ResolvedJavaType type = ObjectStamp.typeOrNull(getObject()); + ResolvedJavaType type = StampTool.typeOrNull(getObject()); if (type != null) { if (type.isArray()) { Method method = ObjectCloneSnippets.arrayCloneMethods.get(type.getComponentType().getKind()); @@ -105,7 +106,7 @@ /* * Looks at the given stamp and determines if it is an exact type (or can be assumed to be an * exact type) and if it is a cloneable type. - * + * * If yes, then the exact type is returned, otherwise it returns null. */ private static ResolvedJavaType getConcreteType(Stamp stamp, Assumptions assumptions, MetaAccessProvider metaAccess) { diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/ObjectCloneSnippets.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/ObjectCloneSnippets.java Fri Apr 25 16:21:07 2014 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/ObjectCloneSnippets.java Mon Apr 28 11:18:15 2014 +0200 @@ -26,7 +26,7 @@ import java.util.*; import com.oracle.graal.api.meta.*; -import com.oracle.graal.graph.*; +import com.oracle.graal.compiler.common.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.java.*; import com.oracle.graal.replacements.*; diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/ObjectGetClassNode.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/ObjectGetClassNode.java Fri Apr 25 16:21:07 2014 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/ObjectGetClassNode.java Mon Apr 28 11:18:15 2014 +0200 @@ -22,7 +22,7 @@ */ package com.oracle.graal.hotspot.replacements; -import static com.oracle.graal.phases.GraalOptions.*; +import static com.oracle.graal.compiler.common.GraalOptions.*; import com.oracle.graal.api.meta.*; import com.oracle.graal.api.meta.ResolvedJavaType.Representation; @@ -67,13 +67,10 @@ if (usages().isEmpty()) { return null; } else { - Stamp stamp = getObject().stamp(); - if (stamp instanceof ObjectStamp) { - ObjectStamp objectStamp = (ObjectStamp) stamp; - if (objectStamp.isExactType()) { - Constant clazz = objectStamp.type().getEncoding(Representation.JavaClass); - return ConstantNode.forConstant(clazz, tool.getMetaAccess(), graph()); - } + if (StampTool.isExactType(getObject())) { + ResolvedJavaType type = StampTool.typeOrNull(getObject()); + Constant clazz = type.getEncoding(Representation.JavaClass); + return ConstantNode.forConstant(clazz, tool.getMetaAccess(), graph()); } return this; } diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/ReflectionGetCallerClassNode.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/ReflectionGetCallerClassNode.java Fri Apr 25 16:21:07 2014 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/ReflectionGetCallerClassNode.java Mon Apr 28 11:18:15 2014 +0200 @@ -25,6 +25,7 @@ import static com.oracle.graal.compiler.GraalCompiler.*; import com.oracle.graal.api.meta.*; +import com.oracle.graal.compiler.common.*; import com.oracle.graal.graph.*; import com.oracle.graal.graph.spi.*; import com.oracle.graal.hotspot.meta.*; diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/SystemIdentityHashCodeNode.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/SystemIdentityHashCodeNode.java Fri Apr 25 16:21:07 2014 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/SystemIdentityHashCodeNode.java Mon Apr 28 11:18:15 2014 +0200 @@ -22,7 +22,7 @@ */ package com.oracle.graal.hotspot.replacements; -import static com.oracle.graal.phases.GraalOptions.*; +import static com.oracle.graal.compiler.common.GraalOptions.*; import com.oracle.graal.api.meta.*; import com.oracle.graal.hotspot.meta.*; diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/ThreadSubstitutions.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/ThreadSubstitutions.java Fri Apr 25 16:21:07 2014 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/ThreadSubstitutions.java Mon Apr 28 11:18:15 2014 +0200 @@ -29,7 +29,7 @@ import com.oracle.graal.api.meta.*; import com.oracle.graal.api.replacements.*; -import com.oracle.graal.graph.*; +import com.oracle.graal.compiler.common.*; import com.oracle.graal.graph.Node.ConstantNodeParameter; import com.oracle.graal.graph.Node.NodeIntrinsic; import com.oracle.graal.hotspot.nodes.*; diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/TypeCheckSnippetUtils.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/TypeCheckSnippetUtils.java Fri Apr 25 16:21:07 2014 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/TypeCheckSnippetUtils.java Mon Apr 28 11:18:15 2014 +0200 @@ -22,9 +22,9 @@ */ package com.oracle.graal.hotspot.replacements; +import static com.oracle.graal.compiler.common.GraalOptions.*; import static com.oracle.graal.hotspot.replacements.HotSpotReplacementsUtil.*; import static com.oracle.graal.nodes.extended.BranchProbabilityNode.*; -import static com.oracle.graal.phases.GraalOptions.*; import java.util.*; diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/UnsafeArrayCopyNode.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/UnsafeArrayCopyNode.java Fri Apr 25 16:21:07 2014 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/UnsafeArrayCopyNode.java Mon Apr 28 11:18:15 2014 +0200 @@ -25,11 +25,11 @@ import static com.oracle.graal.api.meta.LocationIdentity.*; import com.oracle.graal.api.meta.*; +import com.oracle.graal.compiler.common.type.*; import com.oracle.graal.graph.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.extended.*; import com.oracle.graal.nodes.spi.*; -import com.oracle.graal.nodes.type.*; import com.oracle.graal.replacements.SnippetTemplate.Arguments; @NodeInfo(allowedUsageTypes = {InputType.Memory}) diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/WriteBarrierSnippets.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/WriteBarrierSnippets.java Fri Apr 25 16:21:07 2014 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/WriteBarrierSnippets.java Mon Apr 28 11:18:15 2014 +0200 @@ -22,13 +22,14 @@ */ package com.oracle.graal.hotspot.replacements; +import static com.oracle.graal.compiler.common.GraalOptions.*; import static com.oracle.graal.hotspot.replacements.HotSpotReplacementsUtil.*; import static com.oracle.graal.nodes.extended.BranchProbabilityNode.*; -import static com.oracle.graal.phases.GraalOptions.*; import static com.oracle.graal.replacements.SnippetTemplate.*; import com.oracle.graal.api.code.*; import com.oracle.graal.api.meta.*; +import com.oracle.graal.compiler.common.*; import com.oracle.graal.graph.Node.ConstantNodeParameter; import com.oracle.graal.graph.Node.NodeIntrinsic; import com.oracle.graal.hotspot.HotSpotVMConfig.CompressEncoding; @@ -39,7 +40,6 @@ import com.oracle.graal.nodes.HeapAccess.BarrierType; import com.oracle.graal.nodes.extended.*; import com.oracle.graal.nodes.spi.*; -import com.oracle.graal.phases.*; import com.oracle.graal.replacements.*; import com.oracle.graal.replacements.Snippet.ConstantParameter; import com.oracle.graal.replacements.SnippetTemplate.AbstractTemplates; diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/DeoptimizationStub.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/DeoptimizationStub.java Mon Apr 28 11:18:15 2014 +0200 @@ -0,0 +1,292 @@ +/* + * Copyright (c) 2013, 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.graal.hotspot.stubs; + +import static com.oracle.graal.hotspot.replacements.HotSpotReplacementsUtil.*; +import static com.oracle.graal.hotspot.stubs.StubUtil.*; + +import com.oracle.graal.api.code.*; +import com.oracle.graal.api.meta.*; +import com.oracle.graal.asm.*; +import com.oracle.graal.compiler.common.*; +import com.oracle.graal.graph.Node.ConstantNodeParameter; +import com.oracle.graal.graph.Node.NodeIntrinsic; +import com.oracle.graal.hotspot.*; +import com.oracle.graal.hotspot.meta.*; +import com.oracle.graal.hotspot.nodes.*; +import com.oracle.graal.replacements.*; +import com.oracle.graal.replacements.Snippet.*; +import com.oracle.graal.word.*; + +/** + * Deoptimization stub. + * + * This is the entry point for code which is returning to a de-optimized frame. + * + * The steps taken by this frame are as follows: + * + * - push a dummy "register_save" and save the return values (O0, O1, F0/F1, G1) and all potentially + * live registers (at a pollpoint many registers can be live). + * + * - call the C routine: Deoptimization::fetch_unroll_info (this function returns information about + * the number and size of interpreter frames which are equivalent to the frame which is being + * deoptimized) + * + * - deallocate the unpack frame, restoring only results values. Other volatile registers will now + * be captured in the vframeArray as needed. + * + * - deallocate the deoptimization frame + * + * - in a loop using the information returned in the previous step push new interpreter frames (take + * care to propagate the return values through each new frame pushed) + * + * - create a dummy "unpack_frame" and save the return values (O0, O1, F0) + * + * - call the C routine: Deoptimization::unpack_frames (this function lays out values on the + * interpreter frame which was just created) + * + * - deallocate the dummy unpack_frame + * + * - ensure that all the return values are correctly set and then do a return to the interpreter + * entry point + */ +public class DeoptimizationStub extends SnippetStub { + + private final TargetDescription target; + + public DeoptimizationStub(HotSpotProviders providers, TargetDescription target, HotSpotForeignCallLinkage linkage) { + super(providers, target, linkage); + this.target = target; + } + + @Override + public boolean preservesRegisters() { + return false; + } + + @Override + protected Object getConstantParameterValue(int index, String name) { + switch (index) { + case 0: + return providers.getRegisters().getThreadRegister(); + case 1: + return providers.getRegisters().getStackPointerRegister(); + default: + throw GraalInternalError.shouldNotReachHere("unknown parameter " + name + " at index " + index); + } + } + + /** + * Uncommon trap. + * + * We save the argument return registers. We call the first C routine, fetch_unroll_info(). This + * routine captures the return values and returns a structure which describes the current frame + * size and the sizes of all replacement frames. The current frame is compiled code and may + * contain many inlined functions, each with their own JVM state. We pop the current frame, then + * push all the new frames. Then we call the C routine unpack_frames() to populate these frames. + * Finally unpack_frames() returns us the new target address. Notice that callee-save registers + * are BLOWN here; they have already been captured in the vframeArray at the time the return PC + * was patched. + * + *

+ * ATTENTION: We cannot do any complicated operations e.g. logging via printf in this snippet + * because we change the current stack layout and so the code is very sensitive to register + * allocation. + */ + @Snippet + private static void uncommonTrapHandler(@ConstantParameter Register threadRegister, @ConstantParameter Register stackPointerRegister) { + final Word thread = registerAsWord(threadRegister); + long registerSaver = SaveAllRegistersNode.saveAllRegisters(); + + final int actionAndReason = readPendingDeoptimization(thread); + writePendingDeoptimization(thread, -1); + + final Word unrollBlock = UncommonTrapCallNode.uncommonTrap(registerSaver, actionAndReason); + + // Pop all the frames we must move/replace. + // + // Frame picture (youngest to oldest) + // 1: self-frame + // 2: deoptimizing frame + // 3: caller of deoptimizing frame (could be compiled/interpreted). + + // Pop self-frame. + LeaveCurrentStackFrameNode.leaveCurrentStackFrame(); + + // Load the initial info we should save (e.g. frame pointer). + final Word initialInfo = unrollBlock.readWord(deoptimizationUnrollBlockInitialInfoOffset()); + + // Pop deoptimized frame. + final int sizeOfDeoptimizedFrame = unrollBlock.readInt(deoptimizationUnrollBlockSizeOfDeoptimizedFrameOffset()); + LeaveDeoptimizedStackFrameNode.leaveDeoptimizedStackFrame(sizeOfDeoptimizedFrame, initialInfo); + + /* + * Stack bang to make sure there's enough room for the interpreter frames. Bang stack for + * total size of the interpreter frames plus shadow page size. Bang one page at a time + * because large sizes can bang beyond yellow and red zones. + * + * @deprecated This code should go away as soon as JDK-8032410 hits the Graal repository. + */ + final int totalFrameSizes = unrollBlock.readInt(deoptimizationUnrollBlockTotalFrameSizesOffset()); + final int bangPages = NumUtil.roundUp(totalFrameSizes, pageSize()) / pageSize() + stackShadowPages(); + Word stackPointer = readRegister(stackPointerRegister); + + for (int i = 1; i < bangPages; i++) { + stackPointer.writeInt((-i * pageSize()) + stackBias(), 0); + } + + // Load number of interpreter frames. + final int numberOfFrames = unrollBlock.readInt(deoptimizationUnrollBlockNumberOfFramesOffset()); + + // Load address of array of frame sizes. + final Word frameSizes = unrollBlock.readWord(deoptimizationUnrollBlockFrameSizesOffset()); + + // Load address of array of frame PCs. + final Word framePcs = unrollBlock.readWord(deoptimizationUnrollBlockFramePcsOffset()); + + /* + * Get the current stack pointer (sender's original SP) before adjustment so that we can + * save it in the skeletal interpreter frame. + */ + Word senderSp = readRegister(stackPointerRegister); + + // Adjust old interpreter frame to make space for new frame's extra Java locals. + final int callerAdjustment = unrollBlock.readInt(deoptimizationUnrollBlockCallerAdjustmentOffset()); + writeRegister(stackPointerRegister, readRegister(stackPointerRegister).subtract(callerAdjustment)); + + for (int i = 0; i < numberOfFrames; i++) { + final Word frameSize = frameSizes.readWord(i * wordSize()); + final Word framePc = framePcs.readWord(i * wordSize()); + + // Push an interpreter frame onto the stack. + PushInterpreterFrameNode.pushInterpreterFrame(frameSize, framePc, senderSp, initialInfo); + + // Get the current stack pointer (sender SP) and pass it to next frame. + senderSp = readRegister(stackPointerRegister); + } + + // Get final return address. + final Word framePc = framePcs.readWord(numberOfFrames * wordSize()); + + /* + * Enter a frame to call out to unpack frames. Since we changed the stack pointer to an + * unknown alignment we need to align it here before calling C++ code. + */ + final Word senderFp = initialInfo; + EnterUnpackFramesStackFrameNode.enterUnpackFramesStackFrame(framePc, senderSp, senderFp); + + // Pass uncommon trap mode to unpack frames. + final int mode = deoptimizationUnpackUncommonTrap(); + unpackFrames(UNPACK_FRAMES, thread, mode); + + LeaveUnpackFramesStackFrameNode.leaveUnpackFramesStackFrame(); + } + + /** + * Reads the value of the passed register as a Word. + */ + private static Word readRegister(Register register) { + return registerAsWord(register, false, false); + } + + /** + * Writes the value of the passed register. + * + * @param value value the register should be set to + */ + private static void writeRegister(Register register, Word value) { + writeRegisterAsWord(register, value); + } + + @Fold + private static int stackShadowPages() { + return config().useStackBanging ? config().stackShadowPages : 0; + } + + /** + * Returns the stack bias for the host architecture. + * + * @deprecated This method should go away as soon as JDK-8032410 hits the Graal repository. + * + * @return stack bias + */ + @Deprecated + @Fold + private static int stackBias() { + return config().stackBias; + } + + @Fold + private static int deoptimizationUnrollBlockSizeOfDeoptimizedFrameOffset() { + return config().deoptimizationUnrollBlockSizeOfDeoptimizedFrameOffset; + } + + @Fold + private static int deoptimizationUnrollBlockCallerAdjustmentOffset() { + return config().deoptimizationUnrollBlockCallerAdjustmentOffset; + } + + @Fold + private static int deoptimizationUnrollBlockNumberOfFramesOffset() { + return config().deoptimizationUnrollBlockNumberOfFramesOffset; + } + + @Fold + private static int deoptimizationUnrollBlockTotalFrameSizesOffset() { + return config().deoptimizationUnrollBlockTotalFrameSizesOffset; + } + + @Fold + private static int deoptimizationUnrollBlockFrameSizesOffset() { + return config().deoptimizationUnrollBlockFrameSizesOffset; + } + + @Fold + private static int deoptimizationUnrollBlockFramePcsOffset() { + return config().deoptimizationUnrollBlockFramePcsOffset; + } + + @Fold + private static int deoptimizationUnrollBlockInitialInfoOffset() { + return config().deoptimizationUnrollBlockInitialInfoOffset; + } + + @Fold + private static int deoptimizationUnpackDeopt() { + return config().deoptimizationUnpackDeopt; + } + + @Fold + private static int deoptimizationUnpackUncommonTrap() { + return config().deoptimizationUnpackUncommonTrap; + } + + public static final ForeignCallDescriptor FETCH_UNROLL_INFO = descriptorFor(DeoptimizationStub.class, "fetchUnrollInfo"); + public static final ForeignCallDescriptor UNPACK_FRAMES = descriptorFor(DeoptimizationStub.class, "unpackFrames"); + + @NodeIntrinsic(value = StubForeignCallNode.class, setStampFromReturnType = true) + public static native Word fetchUnrollInfo(@ConstantNodeParameter ForeignCallDescriptor fetchUnrollInfo, Word thread); + + @NodeIntrinsic(value = StubForeignCallNode.class, setStampFromReturnType = true) + public static native int unpackFrames(@ConstantNodeParameter ForeignCallDescriptor unpackFrames, Word thread, int mode); +} diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/ForeignCallStub.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/ForeignCallStub.java Fri Apr 25 16:21:07 2014 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/ForeignCallStub.java Mon Apr 28 11:18:15 2014 +0200 @@ -27,6 +27,7 @@ import static com.oracle.graal.hotspot.HotSpotForeignCallLinkage.RegisterEffect.*; import com.oracle.graal.api.meta.*; +import com.oracle.graal.compiler.common.type.*; import com.oracle.graal.debug.*; import com.oracle.graal.hotspot.*; import com.oracle.graal.hotspot.HotSpotForeignCallLinkage.Transition; @@ -34,7 +35,6 @@ import com.oracle.graal.hotspot.nodes.*; import com.oracle.graal.hotspot.replacements.*; import com.oracle.graal.nodes.*; -import com.oracle.graal.nodes.type.*; import com.oracle.graal.replacements.*; import com.oracle.graal.replacements.nodes.*; import com.oracle.graal.word.*; diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/NewArrayStub.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/NewArrayStub.java Fri Apr 25 16:21:07 2014 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/NewArrayStub.java Mon Apr 28 11:18:15 2014 +0200 @@ -22,7 +22,6 @@ */ package com.oracle.graal.hotspot.stubs; -import static com.oracle.graal.hotspot.HotSpotGraalRuntime.*; import static com.oracle.graal.hotspot.replacements.HotSpotReplacementsUtil.*; import static com.oracle.graal.hotspot.replacements.NewObjectSnippets.*; import static com.oracle.graal.hotspot.stubs.NewInstanceStub.*; @@ -61,16 +60,10 @@ protected Arguments makeArguments(SnippetInfo stub) { HotSpotResolvedObjectType intArrayType = (HotSpotResolvedObjectType) providers.getMetaAccess().lookupJavaType(int[].class); - // RuntimeStub cannot (currently) support oops or metadata embedded in the code so we - // convert the hub (i.e., Klass*) for int[] to be a naked word. This should be safe since - // the int[] class will never be unloaded. - Constant intArrayHub = intArrayType.klass(); - intArrayHub = Constant.forIntegerKind(runtime().getTarget().wordKind, intArrayHub.asLong()); - Arguments args = new Arguments(stub, GuardsStage.FLOATING_GUARDS, LoweringTool.StandardLoweringStage.HIGH_TIER); args.add("hub", null); args.add("length", null); - args.addConst("intArrayHub", intArrayHub); + args.addConst("intArrayHub", intArrayType.klass()); args.addConst("threadRegister", providers.getRegisters().getThreadRegister()); return args; } diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/NewInstanceStub.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/NewInstanceStub.java Fri Apr 25 16:21:07 2014 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/NewInstanceStub.java Mon Apr 28 11:18:15 2014 +0200 @@ -22,7 +22,6 @@ */ package com.oracle.graal.hotspot.stubs; -import static com.oracle.graal.hotspot.HotSpotGraalRuntime.*; import static com.oracle.graal.hotspot.nodes.DirectCompareAndSwapNode.*; import static com.oracle.graal.hotspot.replacements.HotSpotReplacementsUtil.*; import static com.oracle.graal.hotspot.stubs.StubUtil.*; @@ -61,15 +60,9 @@ protected Arguments makeArguments(SnippetInfo stub) { HotSpotResolvedObjectType intArrayType = (HotSpotResolvedObjectType) providers.getMetaAccess().lookupJavaType(int[].class); - // RuntimeStub cannot (currently) support oops or metadata embedded in the code so we - // convert the hub (i.e., Klass*) for int[] to be a naked word. This should be safe since - // the int[] class will never be unloaded. - Constant intArrayHub = intArrayType.klass(); - intArrayHub = Constant.forIntegerKind(runtime().getTarget().wordKind, intArrayHub.asLong()); - Arguments args = new Arguments(stub, GuardsStage.FLOATING_GUARDS, LoweringTool.StandardLoweringStage.HIGH_TIER); args.add("hub", null); - args.addConst("intArrayHub", intArrayHub); + args.addConst("intArrayHub", intArrayType.klass()); args.addConst("threadRegister", providers.getRegisters().getThreadRegister()); return args; } @@ -231,7 +224,7 @@ * @param log specifies if logging is enabled * @return the allocated chunk or {@link Word#zero()} if allocation fails */ - static Word edenAllocate(Word sizeInBytes, boolean log) { + public static Word edenAllocate(Word sizeInBytes, boolean log) { Word heapTopAddress = Word.unsigned(heapTopAddress()); Word heapEndAddress = Word.unsigned(heapEndAddress()); diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/SnippetStub.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/SnippetStub.java Fri Apr 25 16:21:07 2014 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/SnippetStub.java Mon Apr 28 11:18:15 2014 +0200 @@ -26,7 +26,7 @@ import com.oracle.graal.api.code.*; import com.oracle.graal.api.meta.*; -import com.oracle.graal.graph.*; +import com.oracle.graal.compiler.common.*; import com.oracle.graal.hotspot.*; import com.oracle.graal.hotspot.meta.*; import com.oracle.graal.nodes.*; diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/Stub.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/Stub.java Fri Apr 25 16:21:07 2014 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/Stub.java Mon Apr 28 11:18:15 2014 +0200 @@ -23,18 +23,18 @@ package com.oracle.graal.hotspot.stubs; import static com.oracle.graal.compiler.GraalCompiler.*; +import static com.oracle.graal.compiler.common.GraalOptions.*; import static com.oracle.graal.hotspot.HotSpotGraalRuntime.*; -import static com.oracle.graal.phases.GraalOptions.*; import java.util.*; import com.oracle.graal.api.code.*; import com.oracle.graal.api.meta.*; +import com.oracle.graal.compiler.common.*; import com.oracle.graal.compiler.target.*; import com.oracle.graal.debug.*; import com.oracle.graal.debug.Debug.Scope; import com.oracle.graal.debug.internal.*; -import com.oracle.graal.graph.*; import com.oracle.graal.hotspot.*; import com.oracle.graal.hotspot.bridge.CompilerToVM.CodeInstallResult; import com.oracle.graal.hotspot.meta.*; @@ -95,7 +95,7 @@ /** * Creates a new stub. - * + * * @param linkage linkage details for a call to the stub */ public Stub(HotSpotProviders providers, HotSpotForeignCallLinkage linkage) { @@ -125,8 +125,7 @@ } /** - * Gets the method the stub's code will be {@linkplain InstalledCode#getMethod() associated} - * with once installed. This may be null. + * Gets the method the stub's code will be associated with once installed. This may be null. */ protected abstract ResolvedJavaMethod getInstalledCodeOwner(); diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.hsail/src/com/oracle/graal/hsail/HSAIL.java --- a/graal/com.oracle.graal.hsail/src/com/oracle/graal/hsail/HSAIL.java Fri Apr 25 16:21:07 2014 +0200 +++ b/graal/com.oracle.graal.hsail/src/com/oracle/graal/hsail/HSAIL.java Mon Apr 28 11:18:15 2014 +0200 @@ -131,6 +131,12 @@ public static final Register d17 = new Register(81, 17, "d17", CPU); public static final Register d18 = new Register(82, 18, "d18", CPU); public static final Register d19 = new Register(83, 19, "d19", CPU); + public static final Register d20 = new Register(84, 20, "d20", CPU); + + public static final Register threadRegister = d20; + public static final Register actionAndReasonReg = s32; + public static final Register codeBufferOffsetReg = s33; + public static final Register dregOopMapReg = s39; // @formatter:off public static final Register[] cRegisters = { @@ -145,7 +151,7 @@ }; public static final Register[] dRegisters = { - d0, d1, d2, d3, d4, d5, d6, d7, d8, d9, d10, d11, d12, d13, d14, d15 + d0, d1, d2, d3, d4, d5, d6, d7, d8, d9, d10, d11, d12, d13, d14, d15, threadRegister }; public static final Register[] qRegisters = { @@ -154,9 +160,12 @@ public static final Register[] allRegisters = { c0, c1, c2, c3, c4, c5, c6, c7, s0, s1, s2, s3, s4, s5, s6, s7, s8, s9, s10, s11, s12, s13, s14, s15, + s16, s17, s18, s19, s20, s21, s22, s23, s24, s25, s26, s27, s28, s29, s30, s31, d0, d1, d2, d3, d4, d5, d6, d7, d8, d9, d10, d11, d12, d13, d14, d15, q0, q1, q2, q3, q4, q5, q6, q7, q8, q9, q10, q11, - q12, q13, q14, q15 + q12, q13, q14, q15, + s32, s33, s34, s35, s36, s37, s38, s39, + d16, d17, d18, d19, threadRegister }; // @formatter:on diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.java.decompiler/src/com/oracle/graal/java/decompiler/Decompiler.java --- a/graal/com.oracle.graal.java.decompiler/src/com/oracle/graal/java/decompiler/Decompiler.java Fri Apr 25 16:21:07 2014 +0200 +++ b/graal/com.oracle.graal.java.decompiler/src/com/oracle/graal/java/decompiler/Decompiler.java Mon Apr 28 11:18:15 2014 +0200 @@ -25,7 +25,7 @@ import java.io.*; import java.util.*; -import com.oracle.graal.graph.*; +import com.oracle.graal.compiler.common.*; import com.oracle.graal.java.decompiler.block.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.cfg.*; diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.java.decompiler/src/com/oracle/graal/java/decompiler/DecompilerLoopSimplify.java --- a/graal/com.oracle.graal.java.decompiler/src/com/oracle/graal/java/decompiler/DecompilerLoopSimplify.java Fri Apr 25 16:21:07 2014 +0200 +++ b/graal/com.oracle.graal.java.decompiler/src/com/oracle/graal/java/decompiler/DecompilerLoopSimplify.java Mon Apr 28 11:18:15 2014 +0200 @@ -25,6 +25,7 @@ import java.io.*; import java.util.*; +import com.oracle.graal.compiler.common.cfg.*; import com.oracle.graal.java.decompiler.block.*; import com.oracle.graal.nodes.cfg.*; @@ -46,7 +47,7 @@ cfgBlocks.remove(0); if (firstBlock.isLoopHeader()) { DecompilerLoopBlock loopBlock = new DecompilerLoopBlock(firstBlock, decompiler, decompiler.getSchedule(), infoStream); - Loop loop = firstBlock.getLoop(); + Loop loop = firstBlock.getLoop(); for (int i = 0; i < cfgBlocks.size(); i++) { if (loop.blocks.contains(cfgBlocks.get(i)) && cfgBlocks.get(i) != firstBlock) { diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.java/src/com/oracle/graal/java/AbstractBytecodeParser.java --- a/graal/com.oracle.graal.java/src/com/oracle/graal/java/AbstractBytecodeParser.java Fri Apr 25 16:21:07 2014 +0200 +++ b/graal/com.oracle.graal.java/src/com/oracle/graal/java/AbstractBytecodeParser.java Mon Apr 28 11:18:15 2014 +0200 @@ -25,8 +25,6 @@ import static com.oracle.graal.api.code.TypeCheckHints.*; import static com.oracle.graal.bytecode.Bytecodes.*; -import static java.lang.reflect.Modifier.*; - import java.util.*; import com.oracle.graal.api.code.*; @@ -34,12 +32,11 @@ import com.oracle.graal.api.meta.ProfilingInfo.TriState; import com.oracle.graal.api.meta.ResolvedJavaType.Representation; import com.oracle.graal.bytecode.*; +import com.oracle.graal.compiler.common.*; +import com.oracle.graal.compiler.common.calc.*; import com.oracle.graal.debug.*; -import com.oracle.graal.graph.*; import com.oracle.graal.java.BciBlockMapping.BciBlock; import com.oracle.graal.nodes.*; -import com.oracle.graal.nodes.calc.*; -import com.oracle.graal.nodes.calc.FloatConvertNode.FloatConvert; import com.oracle.graal.options.*; import com.oracle.graal.phases.*; @@ -327,7 +324,7 @@ private void genArithmeticOp(Kind result, int opcode) { T y = frameState.pop(result); T x = frameState.pop(result); - boolean isStrictFP = isStrict(method.getModifiers()); + boolean isStrictFP = method.isStrict(); T v; switch (opcode) { case IADD: diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.java/src/com/oracle/graal/java/AbstractFrameStateBuilder.java --- a/graal/com.oracle.graal.java/src/com/oracle/graal/java/AbstractFrameStateBuilder.java Fri Apr 25 16:21:07 2014 +0200 +++ b/graal/com.oracle.graal.java/src/com/oracle/graal/java/AbstractFrameStateBuilder.java Mon Apr 28 11:18:15 2014 +0200 @@ -69,6 +69,12 @@ public abstract boolean isCompatibleWith(S other); public void clearNonLiveLocals(BciBlock block, LocalLiveness liveness, boolean liveIn) { + /* + * (lstadler) if somebody is tempted to remove/disable this clearing code: it's possible to + * remove it for normal compilations, but not for OSR compilations - otherwise dead object + * slots at the OSR entry aren't cleared. it is also not enough to rely on PiNodes with + * Kind.Illegal, because the conflicting branch might not have been parsed. + */ if (liveness == null) { return; } diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.java/src/com/oracle/graal/java/BciBlockMapping.java --- a/graal/com.oracle.graal.java/src/com/oracle/graal/java/BciBlockMapping.java Fri Apr 25 16:21:07 2014 +0200 +++ b/graal/com.oracle.graal.java/src/com/oracle/graal/java/BciBlockMapping.java Mon Apr 28 11:18:15 2014 +0200 @@ -23,17 +23,17 @@ package com.oracle.graal.java; import static com.oracle.graal.bytecode.Bytecodes.*; -import static com.oracle.graal.phases.GraalOptions.*; +import static com.oracle.graal.compiler.common.GraalOptions.*; import java.util.*; import com.oracle.graal.api.code.*; import com.oracle.graal.api.meta.*; import com.oracle.graal.bytecode.*; +import com.oracle.graal.compiler.common.cfg.*; import com.oracle.graal.debug.*; import com.oracle.graal.debug.Debug.Scope; import com.oracle.graal.nodes.*; -import com.oracle.graal.nodes.cfg.*; /** * Builds a mapping between bytecodes and basic blocks and builds a conservative control flow graph @@ -82,6 +82,12 @@ public boolean isLoopHeader; public int loopId; + /** + * XXX to be removed - currently only used by baseline compiler + */ + public Loop loop; + public boolean isLoopEnd; + public FixedWithNextNode firstInstruction; public AbstractFrameStateBuilder entryState; @@ -144,14 +150,12 @@ return sb.toString(); } - public Loop getLoop() { - // TODO Auto-generated method stub - return null; + public Loop getLoop() { + return loop; } public int getLoopDepth() { - // TODO Auto-generated method stub - return 0; + return Long.bitCount(loops); } public boolean isLoopHeader() { @@ -159,13 +163,11 @@ } public boolean isLoopEnd() { - // TODO Auto-generated method stub - return false; + return isLoopEnd; } public boolean isExceptionEntry() { - // TODO Auto-generated method stub - return false; + return isExceptionEntry; } public BciBlock getSuccessor(int index) { @@ -716,6 +718,10 @@ for (BciBlock successor : block.getSuccessors()) { // Recursively process successors. loops |= computeBlockOrder(successor); + if (block.visited && successor.active) { + // Reached block via backward branch. + block.isLoopEnd = true; + } } block.loops = loops; diff -r 3dde8d8c95b8 -r 40d0022115ee 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 Fri Apr 25 16:21:07 2014 +0200 +++ b/graal/com.oracle.graal.java/src/com/oracle/graal/java/GraphBuilderPhase.java Mon Apr 28 11:18:15 2014 +0200 @@ -25,10 +25,7 @@ import static com.oracle.graal.api.meta.DeoptimizationAction.*; import static com.oracle.graal.api.meta.DeoptimizationReason.*; import static com.oracle.graal.bytecode.Bytecodes.*; -import static com.oracle.graal.phases.GraalOptions.*; -import static java.lang.reflect.Modifier.*; - -import java.lang.reflect.*; +import static com.oracle.graal.compiler.common.GraalOptions.*; import java.util.*; import com.oracle.graal.api.code.*; @@ -36,6 +33,9 @@ import com.oracle.graal.api.meta.ProfilingInfo.TriState; import com.oracle.graal.api.meta.ResolvedJavaType.Representation; import com.oracle.graal.bytecode.*; +import com.oracle.graal.compiler.common.*; +import com.oracle.graal.compiler.common.calc.*; +import com.oracle.graal.compiler.common.type.*; import com.oracle.graal.debug.*; import com.oracle.graal.graph.*; import com.oracle.graal.graph.Node.ValueNumberable; @@ -44,7 +44,6 @@ import com.oracle.graal.java.BciBlockMapping.LocalLiveness; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.calc.*; -import com.oracle.graal.nodes.calc.FloatConvertNode.FloatConvert; import com.oracle.graal.nodes.extended.*; import com.oracle.graal.nodes.java.*; import com.oracle.graal.nodes.java.MethodCallTargetNode.InvokeKind; @@ -217,9 +216,9 @@ liveness = blockMap.liveness; lastInstr = currentGraph.start(); - if (isSynchronized(method.getModifiers())) { + if (method.isSynchronized()) { // add a monitor enter to the start block - currentGraph.start().setStateAfter(frameState.create(FrameState.BEFORE_BCI)); + currentGraph.start().setStateAfter(frameState.create(BytecodeFrame.BEFORE_BCI)); methodSynchronizedObject = synchronizedObject(frameState, method); lastInstr = genMonitorEnter(methodSynchronizedObject); } @@ -282,12 +281,12 @@ protected void finishPrepare(FixedWithNextNode startInstr) { } - private BciBlock unwindBlock(int bci) { + private BciBlock unwindBlock() { if (unwindBlock == null) { unwindBlock = new ExceptionDispatchBlock(); unwindBlock.startBci = -1; unwindBlock.endBci = -1; - unwindBlock.deoptBci = bci; + unwindBlock.deoptBci = method.isSynchronized() ? BytecodeFrame.UNWIND_BCI : BytecodeFrame.AFTER_EXCEPTION_BCI; unwindBlock.setId(Integer.MAX_VALUE); } return unwindBlock; @@ -407,7 +406,7 @@ } private DispatchBeginNode handleException(ValueNode exceptionObject, int bci) { - assert bci == FrameState.BEFORE_BCI || bci == bci() : "invalid bci"; + assert bci == BytecodeFrame.BEFORE_BCI || bci == bci() : "invalid bci"; Debug.log("Creating exception dispatch edges at %d, exception object=%s, exception seen=%s", bci, exceptionObject, profilingInfo.getExceptionSeen(bci)); BciBlock dispatchBlock = currentBlock.exceptionDispatchBlock(); @@ -417,7 +416,7 @@ * unwind immediately. */ if (bci != currentBlock.endBci || dispatchBlock == null) { - dispatchBlock = unwindBlock(bci); + dispatchBlock = unwindBlock(); } HIRFrameStateBuilder dispatchState = frameState.copy(); @@ -634,7 +633,7 @@ @Override protected void emitNullCheck(ValueNode receiver) { - if (ObjectStamp.isObjectNonNull(receiver.stamp())) { + if (StampTool.isObjectNonNull(receiver.stamp())) { return; } BlockPlaceholderNode trueSucc = currentGraph.add(new BlockPlaceholderNode(this)); @@ -721,7 +720,7 @@ * https://wikis.oracle.com/display/HotSpotInternals/Method+handles * +and+invokedynamic */ - boolean hasReceiver = !isStatic(((ResolvedJavaMethod) target).getModifiers()); + boolean hasReceiver = !((ResolvedJavaMethod) target).isStatic(); Constant appendix = constantPool.lookupAppendix(stream.readCPI(), Bytecodes.INVOKEVIRTUAL); if (appendix != null) { frameState.apush(ConstantNode.forConstant(appendix, metaAccess, currentGraph)); @@ -814,7 +813,7 @@ append(new InfopointNode(InfopointReason.METHOD_END, frameState.create(bci()))); } - synchronizedEpilogue(FrameState.AFTER_BCI, x); + synchronizedEpilogue(BytecodeFrame.AFTER_BCI, x); if (frameState.lockDepth() != 0) { throw new BailoutException("unbalanced monitors"); } @@ -1077,17 +1076,17 @@ * Returns a block begin node with the specified state. If the specified probability is * 0, the block deoptimizes immediately. */ - private AbstractBeginNode createBlockTarget(double probability, BciBlock block, HIRFrameStateBuilder stateAfter) { + private BeginNode createBlockTarget(double probability, BciBlock block, HIRFrameStateBuilder stateAfter) { FixedNode target = createTarget(probability, block, stateAfter); - AbstractBeginNode begin = AbstractBeginNode.begin(target); + BeginNode begin = BeginNode.begin(target); - assert !(target instanceof DeoptimizeNode && begin.stateAfter() != null) : "We are not allowed to set the stateAfter of the begin node, because we have to deoptimize " + assert !(target instanceof DeoptimizeNode && begin instanceof BeginStateSplitNode && ((BeginStateSplitNode) begin).stateAfter() != null) : "We are not allowed to set the stateAfter of the begin node, because we have to deoptimize " + "to a bci _before_ the actual if, so that the interpreter can update the profiling information."; return begin; } private ValueNode synchronizedObject(HIRFrameStateBuilder state, ResolvedJavaMethod target) { - if (isStatic(target.getModifiers())) { + if (target.isStatic()) { return appendConstant(target.getDeclaringClass().getEncoding(Representation.JavaClass)); } else { return state.loadLocal(0); @@ -1153,13 +1152,12 @@ private void createUnwind() { assert frameState.stackSize() == 1 : frameState; ValueNode exception = frameState.apop(); - append(new FixedGuardNode(currentGraph.unique(new IsNullNode(exception)), NullCheckException, InvalidateReprofile, true)); - synchronizedEpilogue(FrameState.AFTER_EXCEPTION_BCI, null); + synchronizedEpilogue(BytecodeFrame.AFTER_EXCEPTION_BCI, null); append(new UnwindNode(exception)); } private void synchronizedEpilogue(int bci, ValueNode returnValue) { - if (Modifier.isSynchronized(method.getModifiers())) { + if (method.isSynchronized()) { MonitorExitNode monitorExit = genMonitorExit(methodSynchronizedObject, returnValue); if (returnValue != null) { frameState.push(returnValue.getKind(), returnValue); @@ -1186,7 +1184,7 @@ ResolvedJavaType resolvedCatchType = (ResolvedJavaType) catchType; for (ResolvedJavaType skippedType : graphBuilderConfig.getSkippedExceptionTypes()) { if (skippedType.isAssignableFrom(resolvedCatchType)) { - BciBlock nextBlock = block.getSuccessorCount() == 1 ? unwindBlock(block.deoptBci) : block.getSuccessor(1); + BciBlock nextBlock = block.getSuccessorCount() == 1 ? unwindBlock() : block.getSuccessor(1); ValueNode exception = frameState.stackAt(0); FixedNode trueSuccessor = currentGraph.add(new DeoptimizeNode(InvalidateReprofile, UnreachedCode)); FixedNode nextDispatch = createTarget(nextBlock, frameState); @@ -1197,7 +1195,7 @@ } if (initialized) { - BciBlock nextBlock = block.getSuccessorCount() == 1 ? unwindBlock(block.deoptBci) : block.getSuccessor(1); + BciBlock nextBlock = block.getSuccessorCount() == 1 ? unwindBlock() : block.getSuccessor(1); ValueNode exception = frameState.stackAt(0); CheckCastNode checkCast = currentGraph.add(new CheckCastNode((ResolvedJavaType) catchType, exception, null, false)); frameState.apop(); @@ -1299,7 +1297,7 @@ frameState.clearNonLiveLocals(currentBlock, liveness, false); } if (lastInstr instanceof StateSplit) { - if (lastInstr.getClass() == AbstractBeginNode.class) { + if (lastInstr.getClass() == BeginNode.class) { // BeginNodes do not need a frame state } else { StateSplit stateSplit = (StateSplit) lastInstr; diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.java/src/com/oracle/graal/java/HIRFrameStateBuilder.java --- a/graal/com.oracle.graal.java/src/com/oracle/graal/java/HIRFrameStateBuilder.java Fri Apr 25 16:21:07 2014 +0200 +++ b/graal/com.oracle.graal.java/src/com/oracle/graal/java/HIRFrameStateBuilder.java Mon Apr 28 11:18:15 2014 +0200 @@ -23,18 +23,16 @@ package com.oracle.graal.java; import static com.oracle.graal.graph.iterators.NodePredicates.*; -import static java.lang.reflect.Modifier.*; - import java.util.*; import com.oracle.graal.api.code.*; import com.oracle.graal.api.meta.*; +import com.oracle.graal.compiler.common.type.*; import com.oracle.graal.debug.*; import com.oracle.graal.graph.Node.Verbosity; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.calc.*; import com.oracle.graal.nodes.java.*; -import com.oracle.graal.nodes.type.*; import com.oracle.graal.nodes.util.*; public class HIRFrameStateBuilder extends AbstractFrameStateBuilder { @@ -55,7 +53,7 @@ int javaIndex = 0; int index = 0; - if (!isStatic(method.getModifiers())) { + if (!method.isStatic()) { // add the receiver ParameterNode receiver = graph.unique(new ParameterNode(javaIndex, StampFactory.declaredNonNull(method.getDeclaringClass()))); storeLocal(javaIndex, receiver); @@ -259,7 +257,7 @@ } } - public void insertProxies(AbstractBeginNode begin) { + public void insertProxies(BeginNode begin) { for (int i = 0; i < localsSize(); i++) { ValueNode value = localAt(i); if (value != null) { @@ -328,6 +326,7 @@ } finally { lockedObjects = lockedObjects.length == 1 ? EMPTY_ARRAY : Arrays.copyOf(lockedObjects, lockedObjects.length - 1); monitorIds = monitorIds.length == 1 ? EMPTY_MONITOR_ARRAY : Arrays.copyOf(monitorIds, monitorIds.length - 1); + assert lockedObjects.length == monitorIds.length; } } diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.java/src/com/oracle/graal/java/VerifyOptionsPhase.java --- a/graal/com.oracle.graal.java/src/com/oracle/graal/java/VerifyOptionsPhase.java Fri Apr 25 16:21:07 2014 +0200 +++ b/graal/com.oracle.graal.java/src/com/oracle/graal/java/VerifyOptionsPhase.java Mon Apr 28 11:18:15 2014 +0200 @@ -24,11 +24,10 @@ package com.oracle.graal.java; import static com.oracle.graal.api.meta.MetaUtil.*; -import static java.lang.reflect.Modifier.*; - import java.util.*; import com.oracle.graal.api.meta.*; +import com.oracle.graal.compiler.common.*; import com.oracle.graal.graph.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.java.*; @@ -114,9 +113,9 @@ if (node instanceof StoreFieldNode) { ResolvedJavaField field = ((StoreFieldNode) node).field(); verify(field.getDeclaringClass().equals(declaringClass), node, "store to field " + format("%H.%n", field)); - verify(isStatic(field.getModifiers()), node, "store to field " + format("%H.%n", field)); + verify(field.isStatic(), node, "store to field " + format("%H.%n", field)); if (optionValueType.isAssignableFrom((ResolvedJavaType) field.getType())) { - verify(isFinal(field.getModifiers()), node, "option field " + format("%H.%n", field) + " not final"); + verify(field.isFinal(), node, "option field " + format("%H.%n", field) + " not final"); } else { verify((field.isSynthetic()), node, "store to non-synthetic field " + format("%H.%n", field)); } diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/except/Catch_NPE_07.java --- a/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/except/Catch_NPE_07.java Fri Apr 25 16:21:07 2014 +0200 +++ b/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/except/Catch_NPE_07.java Mon Apr 28 11:18:15 2014 +0200 @@ -23,8 +23,9 @@ package com.oracle.graal.jtt.except; +import org.junit.*; + import com.oracle.graal.jtt.*; -import com.oracle.graal.test.*; /* */ @@ -61,12 +62,12 @@ } } - @LongTest + @Test public void run0() throws Throwable { runTest("test", 0); } - @LongTest + @Test public void run1() throws Throwable { runTest("test", 1); } diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/except/Catch_Two02.java --- a/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/except/Catch_Two02.java Fri Apr 25 16:21:07 2014 +0200 +++ b/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/except/Catch_Two02.java Mon Apr 28 11:18:15 2014 +0200 @@ -22,8 +22,9 @@ */ package com.oracle.graal.jtt.except; +import org.junit.*; + import com.oracle.graal.jtt.*; -import com.oracle.graal.test.*; /* */ @@ -49,17 +50,17 @@ } } - @LongTest + @Test public void run0() throws Throwable { runTest("test", 0); } - @LongTest + @Test public void run1() throws Throwable { runTest("test", 1); } - @LongTest + @Test public void run2() throws Throwable { runTest("test", 3); } diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/except/Catch_Two03.java --- a/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/except/Catch_Two03.java Fri Apr 25 16:21:07 2014 +0200 +++ b/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/except/Catch_Two03.java Mon Apr 28 11:18:15 2014 +0200 @@ -22,8 +22,9 @@ */ package com.oracle.graal.jtt.except; +import org.junit.*; + import com.oracle.graal.jtt.*; -import com.oracle.graal.test.*; /* */ @@ -56,17 +57,17 @@ } } - @LongTest + @Test public void run0() throws Throwable { runTest("test", 0); } - @LongTest + @Test public void run1() throws Throwable { runTest("test", 1); } - @LongTest + @Test public void run2() throws Throwable { runTest("test", 2); } diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/except/Throw_InNested.java --- a/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/except/Throw_InNested.java Fri Apr 25 16:21:07 2014 +0200 +++ b/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/except/Throw_InNested.java Mon Apr 28 11:18:15 2014 +0200 @@ -24,8 +24,9 @@ */ package com.oracle.graal.jtt.except; +import org.junit.*; + import com.oracle.graal.jtt.*; -import com.oracle.graal.test.*; public class Throw_InNested extends JTTTest { @@ -48,12 +49,12 @@ return i; } - @LongTest + @Test public void run0() throws Throwable { runTest("test", 0); } - @LongTest + @Test public void run1() throws Throwable { runTest("test", 1); } diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/except/Throw_Synchronized01.java --- a/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/except/Throw_Synchronized01.java Fri Apr 25 16:21:07 2014 +0200 +++ b/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/except/Throw_Synchronized01.java Mon Apr 28 11:18:15 2014 +0200 @@ -24,8 +24,9 @@ */ package com.oracle.graal.jtt.except; +import org.junit.*; + import com.oracle.graal.jtt.*; -import com.oracle.graal.test.*; public class Throw_Synchronized01 extends JTTTest { @@ -38,12 +39,12 @@ throw new Exception(); } - @LongTest + @Test public void run0() throws Throwable { runTest("test", 0); } - @LongTest + @Test public void run1() throws Throwable { runTest("test", 1); } diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/except/Throw_Synchronized02.java --- a/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/except/Throw_Synchronized02.java Fri Apr 25 16:21:07 2014 +0200 +++ b/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/except/Throw_Synchronized02.java Mon Apr 28 11:18:15 2014 +0200 @@ -24,8 +24,9 @@ */ package com.oracle.graal.jtt.except; +import org.junit.*; + import com.oracle.graal.jtt.*; -import com.oracle.graal.test.*; public class Throw_Synchronized02 extends JTTTest { @@ -36,12 +37,12 @@ throw new Exception(); } - @LongTest + @Test public void run0() throws Throwable { runTest("test", 0); } - @LongTest + @Test public void run1() throws Throwable { runTest("test", 1); } diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/except/Throw_Synchronized03.java --- a/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/except/Throw_Synchronized03.java Fri Apr 25 16:21:07 2014 +0200 +++ b/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/except/Throw_Synchronized03.java Mon Apr 28 11:18:15 2014 +0200 @@ -24,8 +24,9 @@ */ package com.oracle.graal.jtt.except; +import org.junit.*; + import com.oracle.graal.jtt.*; -import com.oracle.graal.test.*; public class Throw_Synchronized03 extends JTTTest { @@ -41,12 +42,12 @@ throw new Exception(); } - @LongTest + @Test public void run0() throws Throwable { runTest("test", 0); } - @LongTest + @Test public void run1() throws Throwable { runTest("test", 1); } diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/hotpath/HP_allocate01.java --- a/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/hotpath/HP_allocate01.java Fri Apr 25 16:21:07 2014 +0200 +++ b/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/hotpath/HP_allocate01.java Mon Apr 28 11:18:15 2014 +0200 @@ -22,8 +22,9 @@ */ package com.oracle.graal.jtt.hotpath; +import org.junit.*; + import com.oracle.graal.jtt.*; -import com.oracle.graal.test.*; /* */ @@ -37,27 +38,27 @@ return sum; } - @LongTest + @Test public void run0() throws Throwable { runTest("test", 0); } - @LongTest + @Test public void run1() throws Throwable { runTest("test", 1); } - @LongTest + @Test public void run2() throws Throwable { runTest("test", 2); } - @LongTest + @Test public void run3() throws Throwable { runTest("test", 3); } - @LongTest + @Test public void run4() throws Throwable { runTest("test", 80); } diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/hotpath/HP_field04.java --- a/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/hotpath/HP_field04.java Fri Apr 25 16:21:07 2014 +0200 +++ b/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/hotpath/HP_field04.java Mon Apr 28 11:18:15 2014 +0200 @@ -23,8 +23,9 @@ // Checkstyle: stop package com.oracle.graal.jtt.hotpath; +import org.junit.*; + import com.oracle.graal.jtt.*; -import com.oracle.graal.test.*; /* */ @@ -55,12 +56,12 @@ return (int) (b + c + s + i + l + f + d); } - @LongTest + @Test public void run0() throws Throwable { runTest("test", 40); } - @LongTest + @Test public void run1() throws Throwable { runTest("test", 1000); } diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/hotpath/HP_invoke01.java --- a/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/hotpath/HP_invoke01.java Fri Apr 25 16:21:07 2014 +0200 +++ b/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/hotpath/HP_invoke01.java Mon Apr 28 11:18:15 2014 +0200 @@ -24,8 +24,9 @@ package com.oracle.graal.jtt.hotpath; +import org.junit.*; + import com.oracle.graal.jtt.*; -import com.oracle.graal.test.*; /* */ @@ -104,12 +105,12 @@ } } - @LongTest + @Test public void run0() throws Throwable { runTest("test", 40); } - @LongTest + @Test public void run1() throws Throwable { runTest("test", 80); } diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/hotpath/HP_life.java --- a/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/hotpath/HP_life.java Fri Apr 25 16:21:07 2014 +0200 +++ b/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/hotpath/HP_life.java Mon Apr 28 11:18:15 2014 +0200 @@ -25,8 +25,9 @@ import java.util.*; +import org.junit.*; + import com.oracle.graal.jtt.*; -import com.oracle.graal.test.*; /* */ @@ -106,7 +107,7 @@ } } - @LongTest + @Test public void run0() throws Throwable { runTest("test", 5); } diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/hotpath/HP_nest02.java --- a/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/hotpath/HP_nest02.java Fri Apr 25 16:21:07 2014 +0200 +++ b/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/hotpath/HP_nest02.java Mon Apr 28 11:18:15 2014 +0200 @@ -23,8 +23,9 @@ // Checkstyle: stop package com.oracle.graal.jtt.hotpath; +import org.junit.*; + import com.oracle.graal.jtt.*; -import com.oracle.graal.test.*; /* */ @@ -48,7 +49,7 @@ return sum; } - @LongTest + @Test public void run0() throws Throwable { runTest("test", 15); } diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/hotpath/HP_series.java --- a/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/hotpath/HP_series.java Fri Apr 25 16:21:07 2014 +0200 +++ b/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/hotpath/HP_series.java Mon Apr 28 11:18:15 2014 +0200 @@ -24,6 +24,8 @@ package com.oracle.graal.jtt.hotpath; +import org.junit.*; + import com.oracle.graal.jtt.*; /* @@ -104,7 +106,8 @@ * different implementation may return different results. The 11 ulp delta allowed for test(100) * tries to account for that but is not guaranteed to work forever. */ - // @Test + @Ignore("failure-prone because of the variabiliy of pow/cos/sin") + @Test public void run0() throws Throwable { double expected = 0.6248571921291398d; runTestWithDelta(11 * Math.ulp(expected), "test", 100); diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/hotspot/Test6196102.java --- a/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/hotspot/Test6196102.java Fri Apr 25 16:21:07 2014 +0200 +++ b/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/hotspot/Test6196102.java Mon Apr 28 11:18:15 2014 +0200 @@ -22,8 +22,9 @@ */ package com.oracle.graal.jtt.hotspot; +import org.junit.*; + import com.oracle.graal.jtt.*; -import com.oracle.graal.test.*; /** * @bug 6196102 @@ -46,7 +47,7 @@ return "ok"; } - @LongTest + @Test public void run0() throws Throwable { runTest("test"); } diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/hotspot/Test6850611.java --- a/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/hotspot/Test6850611.java Fri Apr 25 16:21:07 2014 +0200 +++ b/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/hotspot/Test6850611.java Mon Apr 28 11:18:15 2014 +0200 @@ -22,8 +22,9 @@ */ package com.oracle.graal.jtt.hotspot; +import org.junit.*; + import com.oracle.graal.jtt.*; -import com.oracle.graal.test.*; //@formatter:off @@ -50,7 +51,7 @@ return 95; } - @LongTest + @Test public void run0() throws Throwable { runTest("test"); } diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/hotspot/Test6959129.java --- a/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/hotspot/Test6959129.java Fri Apr 25 16:21:07 2014 +0200 +++ b/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/hotspot/Test6959129.java Mon Apr 28 11:18:15 2014 +0200 @@ -22,30 +22,16 @@ */ package com.oracle.graal.jtt.hotspot; +import org.junit.*; + import com.oracle.graal.jtt.*; -//@formatter:off - -/** - * @test - * @bug 6959129 - * @summary COMPARISON WITH INTEGER.MAX_INT DOES NOT WORK CORRECTLY IN THE CLIENT VM. - * - * This test will not run properly without assertions - * - * @run main/othervm -ea Test6959129 - */ public class Test6959129 extends JTTTest { - public static int test() { + public static long test() { int min = Integer.MAX_VALUE - 30000; int max = Integer.MAX_VALUE; - try { - maxMoves(min, max); - } catch (AssertionError e) { - return 95; - } - return 97; + return maxMoves(min, max); } /** @@ -55,7 +41,9 @@ long n = n2; long moves = 0; while (n != 1) { - assert n > 1; + if (n <= 1) { + throw new IllegalStateException(); + } if (isEven(n)) { n = n / 2; } else { @@ -86,7 +74,7 @@ return maxmoves; } - //@Test + @Test(timeout = 20000) public void run0() throws Throwable { runTest("test"); } diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/jdk/EnumMap02.java --- a/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/jdk/EnumMap02.java Fri Apr 25 16:21:07 2014 +0200 +++ b/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/jdk/EnumMap02.java Mon Apr 28 11:18:15 2014 +0200 @@ -24,8 +24,9 @@ import java.util.*; +import org.junit.*; + import com.oracle.graal.jtt.*; -import com.oracle.graal.test.*; /* */ @@ -45,17 +46,17 @@ C } - @LongTest + @Test public void run0() throws Throwable { runTest("test", 0); } - @LongTest + @Test public void run1() throws Throwable { runTest("test", 1); } - @LongTest + @Test public void run2() throws Throwable { runTest("test", 2); } diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/jdk/System_setOut.java --- a/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/jdk/System_setOut.java Fri Apr 25 16:21:07 2014 +0200 +++ b/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/jdk/System_setOut.java Mon Apr 28 11:18:15 2014 +0200 @@ -24,8 +24,9 @@ import java.io.*; +import org.junit.*; + import com.oracle.graal.jtt.*; -import com.oracle.graal.test.*; /* */ @@ -58,7 +59,7 @@ out.println(test(10000)); } - @LongTest + @Test public void run0() throws Throwable { runTest("test", 10000); } diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/jdk/UnsafeAccess01.java --- a/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/jdk/UnsafeAccess01.java Fri Apr 25 16:21:07 2014 +0200 +++ b/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/jdk/UnsafeAccess01.java Mon Apr 28 11:18:15 2014 +0200 @@ -24,10 +24,11 @@ import java.lang.reflect.*; +import org.junit.*; + import sun.misc.*; import com.oracle.graal.jtt.*; -import com.oracle.graal.test.*; /* */ @@ -55,7 +56,7 @@ } } - @LongTest + @Test public void run0() throws Throwable { runTest("test"); } diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/lang/ClassLoader_loadClass01.java --- a/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/lang/ClassLoader_loadClass01.java Fri Apr 25 16:21:07 2014 +0200 +++ b/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/lang/ClassLoader_loadClass01.java Mon Apr 28 11:18:15 2014 +0200 @@ -24,8 +24,9 @@ import java.net.*; +import org.junit.*; + import com.oracle.graal.jtt.*; -import com.oracle.graal.test.*; /* */ @@ -43,22 +44,22 @@ return null; } - @LongTest + @Test public void run0() throws Throwable { runTest("test", 0); } - @LongTest + @Test public void run1() throws Throwable { runTest("test", 1); } - @LongTest + @Test public void run2() throws Throwable { runTest("test", 2); } - @LongTest + @Test public void run3() throws Throwable { runTest("test", 5); } diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/lang/Class_Literal01.java --- a/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/lang/Class_Literal01.java Fri Apr 25 16:21:07 2014 +0200 +++ b/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/lang/Class_Literal01.java Mon Apr 28 11:18:15 2014 +0200 @@ -24,8 +24,9 @@ */ package com.oracle.graal.jtt.lang; +import org.junit.*; + import com.oracle.graal.jtt.*; -import com.oracle.graal.test.*; public final class Class_Literal01 extends JTTTest { @@ -45,27 +46,27 @@ return null; } - @LongTest + @Test public void run0() throws Throwable { runTest("test", 0); } - @LongTest + @Test public void run1() throws Throwable { runTest("test", 1); } - @LongTest + @Test public void run2() throws Throwable { runTest("test", 2); } - @LongTest + @Test public void run3() throws Throwable { runTest("test", 3); } - @LongTest + @Test public void run4() throws Throwable { runTest("test", 4); } diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/lang/Class_asSubclass01.java --- a/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/lang/Class_asSubclass01.java Fri Apr 25 16:21:07 2014 +0200 +++ b/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/lang/Class_asSubclass01.java Mon Apr 28 11:18:15 2014 +0200 @@ -24,8 +24,9 @@ */ package com.oracle.graal.jtt.lang; +import org.junit.*; + import com.oracle.graal.jtt.*; -import com.oracle.graal.test.*; public final class Class_asSubclass01 extends JTTTest { @@ -53,27 +54,27 @@ return i; } - @LongTest + @Test public void run0() throws Throwable { runTest("test", 0); } - @LongTest + @Test public void run1() throws Throwable { runTest("test", 1); } - @LongTest + @Test public void run2() throws Throwable { runTest("test", 2); } - @LongTest + @Test public void run3() throws Throwable { runTest("test", 3); } - @LongTest + @Test public void run4() throws Throwable { runTest("test", 4); } diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/lang/Class_cast01.java --- a/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/lang/Class_cast01.java Fri Apr 25 16:21:07 2014 +0200 +++ b/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/lang/Class_cast01.java Mon Apr 28 11:18:15 2014 +0200 @@ -24,8 +24,9 @@ */ package com.oracle.graal.jtt.lang; +import org.junit.*; + import com.oracle.graal.jtt.*; -import com.oracle.graal.test.*; public final class Class_cast01 extends JTTTest { @@ -57,27 +58,27 @@ return i; } - @LongTest + @Test public void run0() throws Throwable { runTest("test", 1); } - @LongTest + @Test public void run1() throws Throwable { runTest("test", 0); } - @LongTest + @Test public void run2() throws Throwable { runTest("test", 3); } - @LongTest + @Test public void run3() throws Throwable { runTest("test", 2); } - @LongTest + @Test public void run4() throws Throwable { runTest("test", 4); } diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/lang/Class_forName01.java --- a/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/lang/Class_forName01.java Fri Apr 25 16:21:07 2014 +0200 +++ b/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/lang/Class_forName01.java Mon Apr 28 11:18:15 2014 +0200 @@ -24,8 +24,9 @@ */ package com.oracle.graal.jtt.lang; +import org.junit.*; + import com.oracle.graal.jtt.*; -import com.oracle.graal.test.*; public final class Class_forName01 extends JTTTest { @@ -45,27 +46,27 @@ return null; } - @LongTest + @Test public void run0() throws Throwable { runTest("test", 0); } - @LongTest + @Test public void run1() throws Throwable { runTest("test", 1); } - @LongTest + @Test public void run2() throws Throwable { runTest("test", 2); } - @LongTest + @Test public void run3() throws Throwable { runTest("test", 3); } - @LongTest + @Test public void run4() throws Throwable { runTest("test", 4); } diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/lang/Class_forName02.java --- a/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/lang/Class_forName02.java Fri Apr 25 16:21:07 2014 +0200 +++ b/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/lang/Class_forName02.java Mon Apr 28 11:18:15 2014 +0200 @@ -24,8 +24,9 @@ */ package com.oracle.graal.jtt.lang; +import org.junit.*; + import com.oracle.graal.jtt.*; -import com.oracle.graal.test.*; public final class Class_forName02 extends JTTTest { @@ -51,27 +52,27 @@ return null; } - @LongTest + @Test public void run0() throws Throwable { runTest("test", 0); } - @LongTest + @Test public void run1() throws Throwable { runTest("test", 1); } - @LongTest + @Test public void run2() throws Throwable { runTest("test", 2); } - @LongTest + @Test public void run3() throws Throwable { runTest("test", 3); } - @LongTest + @Test public void run4() throws Throwable { runTest("test", 4); } diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/lang/Class_forName03.java --- a/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/lang/Class_forName03.java Fri Apr 25 16:21:07 2014 +0200 +++ b/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/lang/Class_forName03.java Mon Apr 28 11:18:15 2014 +0200 @@ -24,8 +24,9 @@ import java.net.*; +import org.junit.*; + import com.oracle.graal.jtt.*; -import com.oracle.graal.test.*; /* */ @@ -56,32 +57,32 @@ return null; } - @LongTest + @Test public void run0() throws Throwable { runTest("test", 0); } - @LongTest + @Test public void run1() throws Throwable { runTest("test", 1); } - @LongTest + @Test public void run2() throws Throwable { runTest("test", 2); } - @LongTest + @Test public void run3() throws Throwable { runTest("test", 3); } - @LongTest + @Test public void run4() throws Throwable { runTest("test", 4); } - @LongTest + @Test public void run5() throws Throwable { runTest("test", 5); } diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/lang/Class_forName04.java --- a/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/lang/Class_forName04.java Fri Apr 25 16:21:07 2014 +0200 +++ b/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/lang/Class_forName04.java Mon Apr 28 11:18:15 2014 +0200 @@ -22,8 +22,9 @@ */ package com.oracle.graal.jtt.lang; +import org.junit.*; + import com.oracle.graal.jtt.*; -import com.oracle.graal.test.*; /* */ @@ -48,32 +49,32 @@ return null; } - @LongTest + @Test public void run0() throws Throwable { runTest("test", 0); } - @LongTest + @Test public void run1() throws Throwable { runTest("test", 1); } - @LongTest + @Test public void run2() throws Throwable { runTest("test", 2); } - @LongTest + @Test public void run3() throws Throwable { runTest("test", 3); } - @LongTest + @Test public void run4() throws Throwable { runTest("test", 4); } - @LongTest + @Test public void run5() throws Throwable { runTest("test", 5); } diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/lang/Class_forName05.java --- a/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/lang/Class_forName05.java Fri Apr 25 16:21:07 2014 +0200 +++ b/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/lang/Class_forName05.java Mon Apr 28 11:18:15 2014 +0200 @@ -24,8 +24,9 @@ import java.net.*; +import org.junit.*; + import com.oracle.graal.jtt.*; -import com.oracle.graal.test.*; /* */ @@ -41,17 +42,17 @@ return null; } - @LongTest + @Test public void run0() throws Throwable { runTest("test", 0); } - @LongTest + @Test public void run1() throws Throwable { runTest("test", 1); } - @LongTest + @Test public void run2() throws Throwable { runTest("test", 5); } diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/lang/Class_getInterfaces01.java --- a/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/lang/Class_getInterfaces01.java Fri Apr 25 16:21:07 2014 +0200 +++ b/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/lang/Class_getInterfaces01.java Mon Apr 28 11:18:15 2014 +0200 @@ -22,8 +22,9 @@ */ package com.oracle.graal.jtt.lang; +import org.junit.*; + import com.oracle.graal.jtt.*; -import com.oracle.graal.test.*; /* */ @@ -81,27 +82,27 @@ } - @LongTest + @Test public void run0() throws Throwable { runTest("test", 0); } - @LongTest + @Test public void run1() throws Throwable { runTest("test", 1); } - @LongTest + @Test public void run2() throws Throwable { runTest("test", 2); } - @LongTest + @Test public void run3() throws Throwable { runTest("test", 3); } - @LongTest + @Test public void run4() throws Throwable { runTest("test", 4); } diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/lang/Int_less02.java --- a/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/lang/Int_less02.java Fri Apr 25 16:21:07 2014 +0200 +++ b/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/lang/Int_less02.java Mon Apr 28 11:18:15 2014 +0200 @@ -20,8 +20,6 @@ * or visit www.oracle.com if you need additional information or have any * questions. */ -/* - */ package com.oracle.graal.jtt.lang; import org.junit.*; diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/lang/JDK_ClassLoaders02.java --- a/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/lang/JDK_ClassLoaders02.java Fri Apr 25 16:21:07 2014 +0200 +++ b/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/lang/JDK_ClassLoaders02.java Mon Apr 28 11:18:15 2014 +0200 @@ -20,26 +20,6 @@ * or visit www.oracle.com if you need additional information or have any * questions. */ -/* - * Copyright (c) 2007, 2012, Oracle and/or its affiliates. All rights reserved. - * - * Sun Microsystems, Inc. has intellectual property rights relating to technology embodied in the product - * that is described in this document. In particular, and without limitation, these intellectual property - * rights may include one or more of the U.S. patents listed at http://www.sun.com/patents and one or - * more additional patents or pending patent applications in the U.S. and in other countries. - * - * U.S. Government Rights - Commercial software. Government users are subject to the Sun - * Microsystems, Inc. standard license agreement and applicable provisions of the FAR and its - * supplements. - * - * Use is subject to license terms. Sun, Sun Microsystems, the Sun logo, Java and Solaris are trademarks or - * registered trademarks of Sun Microsystems, Inc. in the U.S. and other countries. All SPARC trademarks - * are used under license and are trademarks or registered trademarks of SPARC International, Inc. in the - * U.S. and other countries. - * - * UNIX is a registered trademark in the U.S. and other countries, exclusively licensed through X/Open - * Company, Ltd. - */ package com.oracle.graal.jtt.lang; import java.net.*; diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/lang/LambdaEagerTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/lang/LambdaEagerTest.java Mon Apr 28 11:18:15 2014 +0200 @@ -0,0 +1,86 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.graal.jtt.lang; + +import java.util.*; +import java.util.function.*; + +import org.junit.*; + +import com.oracle.graal.api.code.*; +import com.oracle.graal.api.meta.*; +import com.oracle.graal.compiler.common.*; +import com.oracle.graal.compiler.test.*; +import com.oracle.graal.nodes.*; +import com.oracle.graal.options.*; +import com.oracle.graal.options.OptionValue.OverrideScope; + +public class LambdaEagerTest extends GraalCompilerTest { + + private static final EnumSet UNRESOLVED_UNREACHED = EnumSet.of(DeoptimizationReason.Unresolved, DeoptimizationReason.UnreachedCode); + + private static int doBinary(IntBinaryOperator op, int x, int y) { + return op.applyAsInt(x, y); + } + + private static int add(int x, int y) { + return x + y; + } + + public static int nonCapturing(int x, int y) { + return doBinary((a, b) -> a + b, x, y); + } + + public static int nonCapturing2(int x, int y) { + return doBinary(LambdaEagerTest::add, x, y); + } + + public static int capturing(int x, int y, int z) { + return doBinary((a, b) -> a + b - z, x, y); + } + + @Test + public void testEagerResolveNonCapturing01() { + Result expected = new Result(3, null); + testAgainstExpected(getMethod("nonCapturing"), expected, UNRESOLVED_UNREACHED, 1, 2); + } + + @Test + public void testEagerResolveNonCapturing02() { + Result expected = new Result(3, null); + testAgainstExpected(getMethod("nonCapturing2"), expected, UNRESOLVED_UNREACHED, 1, 2); + } + + @Test + public void testEagerResolveCapturing() { + Result expected = new Result(0, null); + testAgainstExpected(getMethod("capturing"), expected, UNRESOLVED_UNREACHED, 1, 2, 3); + } + + @Override + protected InstalledCode getCode(ResolvedJavaMethod method, StructuredGraph graph, boolean forceCompile) { + try (OverrideScope scope = OptionValue.override(GraalOptions.InlineEverything, true)) { + return super.getCode(method, graph, forceCompile); + } + } +} \ No newline at end of file diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/lang/Object_getClass01.java --- a/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/lang/Object_getClass01.java Fri Apr 25 16:21:07 2014 +0200 +++ b/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/lang/Object_getClass01.java Mon Apr 28 11:18:15 2014 +0200 @@ -24,8 +24,9 @@ */ package com.oracle.graal.jtt.lang; +import org.junit.*; + import com.oracle.graal.jtt.*; -import com.oracle.graal.test.*; public final class Object_getClass01 extends JTTTest { @@ -49,27 +50,27 @@ return null; } - @LongTest + @Test public void run0() throws Throwable { runTest("test", 0); } - @LongTest + @Test public void run1() throws Throwable { runTest("test", 1); } - @LongTest + @Test public void run2() throws Throwable { runTest("test", 2); } - @LongTest + @Test public void run3() throws Throwable { runTest("test", 3); } - @LongTest + @Test public void run4() throws Throwable { runTest("test", 4); } diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/lang/Object_toString01.java --- a/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/lang/Object_toString01.java Fri Apr 25 16:21:07 2014 +0200 +++ b/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/lang/Object_toString01.java Mon Apr 28 11:18:15 2014 +0200 @@ -24,8 +24,9 @@ */ package com.oracle.graal.jtt.lang; +import org.junit.*; + import com.oracle.graal.jtt.*; -import com.oracle.graal.test.*; public class Object_toString01 extends JTTTest { @@ -47,17 +48,17 @@ return string; } - @LongTest + @Test public void run0() throws Throwable { runTest("test", 0); } - @LongTest + @Test public void run1() throws Throwable { runTest("test", 1); } - @LongTest + @Test public void run2() throws Throwable { runTest("test", 2); } diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/lang/String_intern02.java --- a/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/lang/String_intern02.java Fri Apr 25 16:21:07 2014 +0200 +++ b/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/lang/String_intern02.java Mon Apr 28 11:18:15 2014 +0200 @@ -22,8 +22,9 @@ */ package com.oracle.graal.jtt.lang; +import org.junit.*; + import com.oracle.graal.jtt.*; -import com.oracle.graal.test.*; /* */ @@ -33,17 +34,17 @@ return ("id" + i).intern() == ("id" + i).intern(); } - @LongTest + @Test public void run0() throws Throwable { runTest("test", 0); } - @LongTest + @Test public void run1() throws Throwable { runTest("test", 1); } - @LongTest + @Test public void run2() throws Throwable { runTest("test", 2); } diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/lang/String_intern03.java --- a/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/lang/String_intern03.java Fri Apr 25 16:21:07 2014 +0200 +++ b/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/lang/String_intern03.java Mon Apr 28 11:18:15 2014 +0200 @@ -22,8 +22,9 @@ */ package com.oracle.graal.jtt.lang; +import org.junit.*; + import com.oracle.graal.jtt.*; -import com.oracle.graal.test.*; /* */ @@ -33,17 +34,17 @@ return ("id" + i).intern().equals("id" + i); } - @LongTest + @Test public void run0() throws Throwable { runTest("test", 0); } - @LongTest + @Test public void run1() throws Throwable { runTest("test", 1); } - @LongTest + @Test public void run2() throws Throwable { runTest("test", 2); } diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/loop/Loop07.java --- a/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/loop/Loop07.java Fri Apr 25 16:21:07 2014 +0200 +++ b/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/loop/Loop07.java Mon Apr 28 11:18:15 2014 +0200 @@ -26,8 +26,6 @@ import com.oracle.graal.jtt.*; -/* - */ public class Loop07 extends JTTTest { public static String test(int arg) { diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/loop/Loop07_2.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/loop/Loop07_2.java Mon Apr 28 11:18:15 2014 +0200 @@ -0,0 +1,54 @@ +/* + * Copyright (c) 2014, 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.graal.jtt.loop; + +import org.junit.*; + +import com.oracle.graal.jtt.*; + +public class Loop07_2 extends JTTTest { + + public static int test(int arg) { + int count = arg; + for (int i = 0; i < arg; i++) { + count++; + } + return count; + } + + @Test + public void run0() throws Throwable { + runTest("test", 0); + } + + @Test + public void run1() throws Throwable { + runTest("test", 10); + } + + @Test + public void run2() throws Throwable { + runTest("test", 25); + } + +} diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/loop/LoopParseLong.java --- a/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/loop/LoopParseLong.java Fri Apr 25 16:21:07 2014 +0200 +++ b/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/loop/LoopParseLong.java Mon Apr 28 11:18:15 2014 +0200 @@ -22,8 +22,9 @@ */ package com.oracle.graal.jtt.loop; +import org.junit.*; + import com.oracle.graal.jtt.*; -import com.oracle.graal.test.*; public class LoopParseLong extends JTTTest { @@ -98,7 +99,7 @@ return negative ? result : -result; } - @LongTest + @Test public void run0() throws Throwable { runTest("testShortened", "7", 10); runTest("testShortened", "-100", 10); diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/loop/LoopSwitch01.java --- a/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/loop/LoopSwitch01.java Fri Apr 25 16:21:07 2014 +0200 +++ b/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/loop/LoopSwitch01.java Mon Apr 28 11:18:15 2014 +0200 @@ -22,8 +22,9 @@ */ package com.oracle.graal.jtt.loop; +import org.junit.*; + import com.oracle.graal.jtt.*; -import com.oracle.graal.test.*; /* */ @@ -58,7 +59,7 @@ return "" + ('a' + count); } - @LongTest + @Test public void run0() throws Throwable { runTest("test"); } diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/micro/BigObjectParams02.java --- a/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/micro/BigObjectParams02.java Fri Apr 25 16:21:07 2014 +0200 +++ b/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/micro/BigObjectParams02.java Mon Apr 28 11:18:15 2014 +0200 @@ -22,8 +22,9 @@ */ package com.oracle.graal.jtt.micro; +import org.junit.*; + import com.oracle.graal.jtt.*; -import com.oracle.graal.test.*; /* */ @@ -33,7 +34,7 @@ return p0 + p1 + p2 + p3 + p4 + p5 + p6 + p7 + p8 + p9; } - @LongTest + @Test public void run0() throws Throwable { runTest("test", "0", "1", "2", "3", "4", "5", "6", "7", "8", "9"); } diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/micro/FloatingReads.java --- a/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/micro/FloatingReads.java Fri Apr 25 16:21:07 2014 +0200 +++ b/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/micro/FloatingReads.java Mon Apr 28 11:18:15 2014 +0200 @@ -22,6 +22,8 @@ */ package com.oracle.graal.jtt.micro; +import org.junit.*; + import com.oracle.graal.jtt.*; public class FloatingReads extends JTTTest { @@ -61,22 +63,22 @@ return a + b + c; } - // @Test + @Test public void run0() { runTest("test", 10); } - // @Test + @Test public void run1() { runTest("test", 1000); } - // @Test + @Test public void run2() { runTest("test", 1); } - // @Test + @Test public void run3() { runTest("test", 0); } diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/micro/Matrix01.java --- a/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/micro/Matrix01.java Fri Apr 25 16:21:07 2014 +0200 +++ b/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/micro/Matrix01.java Mon Apr 28 11:18:15 2014 +0200 @@ -22,8 +22,9 @@ */ package com.oracle.graal.jtt.micro; +import org.junit.*; + import com.oracle.graal.jtt.*; -import com.oracle.graal.test.*; /* */ @@ -155,32 +156,32 @@ ((Matrix[]) array)[val % array.length] = new Matrix(number); } - @LongTest + @Test public void run0() throws Throwable { runTest("test", 0); } - @LongTest + @Test public void run1() throws Throwable { runTest("test", 1); } - @LongTest + @Test public void run2() throws Throwable { runTest("test", 2); } - @LongTest + @Test public void run3() throws Throwable { runTest("test", 3); } - @LongTest + @Test public void run4() throws Throwable { runTest("test", 4); } - @LongTest + @Test public void run5() throws Throwable { runTest("test", 5); } diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/micro/ReferenceMap01.java --- a/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/micro/ReferenceMap01.java Fri Apr 25 16:21:07 2014 +0200 +++ b/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/micro/ReferenceMap01.java Mon Apr 28 11:18:15 2014 +0200 @@ -22,8 +22,9 @@ */ package com.oracle.graal.jtt.micro; +import org.junit.*; + import com.oracle.graal.jtt.*; -import com.oracle.graal.test.*; /* */ @@ -57,7 +58,7 @@ return Integer.valueOf(foo(new String[]{"asdf"})); } - @LongTest + @Test public void run0() throws Throwable { runTest("test"); } diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/micro/StrangeFrames.java --- a/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/micro/StrangeFrames.java Fri Apr 25 16:21:07 2014 +0200 +++ b/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/micro/StrangeFrames.java Mon Apr 28 11:18:15 2014 +0200 @@ -22,8 +22,9 @@ */ package com.oracle.graal.jtt.micro; +import org.junit.*; + import com.oracle.graal.jtt.*; -import com.oracle.graal.test.*; /* */ @@ -58,7 +59,7 @@ Object c = b; } - @LongTest + @Test public void run0() throws Throwable { runTest("test", 0); } diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/optimize/Conditional01.java --- a/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/optimize/Conditional01.java Fri Apr 25 16:21:07 2014 +0200 +++ b/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/optimize/Conditional01.java Mon Apr 28 11:18:15 2014 +0200 @@ -24,8 +24,9 @@ import java.util.*; +import org.junit.*; + import com.oracle.graal.jtt.*; -import com.oracle.graal.test.*; /* */ @@ -117,22 +118,22 @@ return c2 ? 1 : 0; } - @LongTest + @Test public void run0() throws Throwable { runTest("test", 0); } - @LongTest + @Test public void run1() throws Throwable { runTest("test", 10); } - @LongTest + @Test public void run2() throws Throwable { runTest("test", 20); } - @LongTest + @Test public void run3() throws Throwable { runTest("test", 40); } diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/optimize/NCE_FlowSensitive05.java --- a/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/optimize/NCE_FlowSensitive05.java Fri Apr 25 16:21:07 2014 +0200 +++ b/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/optimize/NCE_FlowSensitive05.java Mon Apr 28 11:18:15 2014 +0200 @@ -24,8 +24,9 @@ import java.io.*; +import org.junit.*; + import com.oracle.graal.jtt.*; -import com.oracle.graal.test.*; /* */ @@ -44,7 +45,7 @@ return (String) arg; } - @LongTest + @Test public void run0() throws Throwable { runTest("test", (Object) null); } diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/optimize/VN_InstanceOf02.java --- a/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/optimize/VN_InstanceOf02.java Fri Apr 25 16:21:07 2014 +0200 +++ b/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/optimize/VN_InstanceOf02.java Mon Apr 28 11:18:15 2014 +0200 @@ -22,8 +22,9 @@ */ package com.oracle.graal.jtt.optimize; +import org.junit.*; + import com.oracle.graal.jtt.*; -import com.oracle.graal.test.*; /* * Tests value numbering of instanceof operations. @@ -76,17 +77,17 @@ return false; } - @LongTest + @Test public void run0() throws Throwable { runTest("test", 0); } - @LongTest + @Test public void run1() throws Throwable { runTest("test", 1); } - @LongTest + @Test public void run2() throws Throwable { runTest("test", 2); } diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/reflect/Class_getField01.java --- a/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/reflect/Class_getField01.java Fri Apr 25 16:21:07 2014 +0200 +++ b/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/reflect/Class_getField01.java Mon Apr 28 11:18:15 2014 +0200 @@ -22,8 +22,9 @@ */ package com.oracle.graal.jtt.reflect; +import org.junit.*; + import com.oracle.graal.jtt.*; -import com.oracle.graal.test.*; /* */ @@ -37,22 +38,22 @@ return Class_getField01.class.getField(input).getName(); } - @LongTest + @Test public void run0() throws Throwable { runTest("test", "test"); } - @LongTest + @Test public void run1() throws Throwable { runTest("test", "field"); } - @LongTest + @Test public void run2() throws Throwable { runTest("test", "field2"); } - @LongTest + @Test public void run3() throws Throwable { runTest("test", "field3"); } diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/reflect/Class_getField02.java --- a/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/reflect/Class_getField02.java Fri Apr 25 16:21:07 2014 +0200 +++ b/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/reflect/Class_getField02.java Mon Apr 28 11:18:15 2014 +0200 @@ -22,8 +22,9 @@ */ package com.oracle.graal.jtt.reflect; +import org.junit.*; + import com.oracle.graal.jtt.*; -import com.oracle.graal.test.*; /* */ @@ -42,27 +43,27 @@ public String field4; } - @LongTest + @Test public void run0() throws Throwable { runTest("test", "test"); } - @LongTest + @Test public void run1() throws Throwable { runTest("test", "field"); } - @LongTest + @Test public void run2() throws Throwable { runTest("test", "field2"); } - @LongTest + @Test public void run3() throws Throwable { runTest("test", "field3"); } - @LongTest + @Test public void run4() throws Throwable { runTest("test", "field4"); } diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/reflect/Class_getMethod01.java --- a/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/reflect/Class_getMethod01.java Fri Apr 25 16:21:07 2014 +0200 +++ b/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/reflect/Class_getMethod01.java Mon Apr 28 11:18:15 2014 +0200 @@ -22,8 +22,9 @@ */ package com.oracle.graal.jtt.reflect; +import org.junit.*; + import com.oracle.graal.jtt.*; -import com.oracle.graal.test.*; /* */ @@ -39,17 +40,17 @@ field = args[0]; } - @LongTest + @Test public void run0() throws Throwable { runTest("test", "test"); } - @LongTest + @Test public void run1() throws Throwable { runTest("test", "main"); } - @LongTest + @Test public void run2() throws Throwable { runTest("test", "xx"); } diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/reflect/Class_getMethod02.java --- a/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/reflect/Class_getMethod02.java Fri Apr 25 16:21:07 2014 +0200 +++ b/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/reflect/Class_getMethod02.java Mon Apr 28 11:18:15 2014 +0200 @@ -22,8 +22,9 @@ */ package com.oracle.graal.jtt.reflect; +import org.junit.*; + import com.oracle.graal.jtt.*; -import com.oracle.graal.test.*; /* */ @@ -52,37 +53,37 @@ field = args[0]; } - @LongTest + @Test public void run0() throws Throwable { runTest("test", 0); } - @LongTest + @Test public void run1() throws Throwable { runTest("test", 1); } - @LongTest + @Test public void run2() throws Throwable { runTest("test", 2); } - @LongTest + @Test public void run3() throws Throwable { runTest("test", 3); } - @LongTest + @Test public void run4() throws Throwable { runTest("test", 4); } - @LongTest + @Test public void run5() throws Throwable { runTest("test", 5); } - @LongTest + @Test public void run6() throws Throwable { runTest("test", 6); } diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/reflect/Class_newInstance03.java --- a/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/reflect/Class_newInstance03.java Fri Apr 25 16:21:07 2014 +0200 +++ b/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/reflect/Class_newInstance03.java Mon Apr 28 11:18:15 2014 +0200 @@ -24,8 +24,9 @@ */ package com.oracle.graal.jtt.reflect; +import org.junit.*; + import com.oracle.graal.jtt.*; -import com.oracle.graal.test.*; public class Class_newInstance03 extends JTTTest { @@ -45,27 +46,27 @@ return false; } - @LongTest + @Test public void run0() throws Throwable { runTest("test", 0); } - @LongTest + @Test public void run1() throws Throwable { runTest("test", 1); } - @LongTest + @Test public void run2() throws Throwable { runTest("test", 2); } - @LongTest + @Test public void run3() throws Throwable { runTest("test", 3); } - @LongTest + @Test public void run4() throws Throwable { runTest("test", 4); } diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/reflect/Field_get01.java --- a/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/reflect/Field_get01.java Fri Apr 25 16:21:07 2014 +0200 +++ b/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/reflect/Field_get01.java Mon Apr 28 11:18:15 2014 +0200 @@ -22,8 +22,9 @@ */ package com.oracle.graal.jtt.reflect; +import org.junit.*; + import com.oracle.graal.jtt.*; -import com.oracle.graal.test.*; /* */ @@ -59,47 +60,47 @@ return false; } - @LongTest + @Test public void run0() throws Throwable { runTest("test", 0); } - @LongTest + @Test public void run1() throws Throwable { runTest("test", 1); } - @LongTest + @Test public void run2() throws Throwable { runTest("test", 2); } - @LongTest + @Test public void run3() throws Throwable { runTest("test", 3); } - @LongTest + @Test public void run4() throws Throwable { runTest("test", 4); } - @LongTest + @Test public void run5() throws Throwable { runTest("test", 5); } - @LongTest + @Test public void run6() throws Throwable { runTest("test", 6); } - @LongTest + @Test public void run7() throws Throwable { runTest("test", 7); } - @LongTest + @Test public void run8() throws Throwable { runTest("test", 8); } diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/reflect/Field_get02.java --- a/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/reflect/Field_get02.java Fri Apr 25 16:21:07 2014 +0200 +++ b/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/reflect/Field_get02.java Mon Apr 28 11:18:15 2014 +0200 @@ -22,8 +22,9 @@ */ package com.oracle.graal.jtt.reflect; +import org.junit.*; + import com.oracle.graal.jtt.*; -import com.oracle.graal.test.*; /* */ @@ -61,47 +62,47 @@ return false; } - @LongTest + @Test public void run0() throws Throwable { runTest("test", 0); } - @LongTest + @Test public void run1() throws Throwable { runTest("test", 1); } - @LongTest + @Test public void run2() throws Throwable { runTest("test", 2); } - @LongTest + @Test public void run3() throws Throwable { runTest("test", 3); } - @LongTest + @Test public void run4() throws Throwable { runTest("test", 4); } - @LongTest + @Test public void run5() throws Throwable { runTest("test", 5); } - @LongTest + @Test public void run6() throws Throwable { runTest("test", 6); } - @LongTest + @Test public void run7() throws Throwable { runTest("test", 7); } - @LongTest + @Test public void run8() throws Throwable { runTest("test", 8); } diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/reflect/Field_get03.java --- a/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/reflect/Field_get03.java Fri Apr 25 16:21:07 2014 +0200 +++ b/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/reflect/Field_get03.java Mon Apr 28 11:18:15 2014 +0200 @@ -24,8 +24,9 @@ import java.lang.reflect.*; +import org.junit.*; + import com.oracle.graal.jtt.*; -import com.oracle.graal.test.*; /* */ @@ -87,47 +88,47 @@ return false; } - @LongTest + @Test public void run0() throws Throwable { runTest("test", 0); } - @LongTest + @Test public void run1() throws Throwable { runTest("test", 1); } - @LongTest + @Test public void run2() throws Throwable { runTest("test", 2); } - @LongTest + @Test public void run3() throws Throwable { runTest("test", 3); } - @LongTest + @Test public void run4() throws Throwable { runTest("test", 4); } - @LongTest + @Test public void run5() throws Throwable { runTest("test", 5); } - @LongTest + @Test public void run6() throws Throwable { runTest("test", 6); } - @LongTest + @Test public void run7() throws Throwable { runTest("test", 7); } - @LongTest + @Test public void run8() throws Throwable { runTest("test", 8); } diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/reflect/Field_get04.java --- a/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/reflect/Field_get04.java Fri Apr 25 16:21:07 2014 +0200 +++ b/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/reflect/Field_get04.java Mon Apr 28 11:18:15 2014 +0200 @@ -22,8 +22,9 @@ */ package com.oracle.graal.jtt.reflect; +import org.junit.*; + import com.oracle.graal.jtt.*; -import com.oracle.graal.test.*; /* */ @@ -61,47 +62,47 @@ return false; } - @LongTest + @Test public void run0() throws Throwable { runTest("test", 0); } - @LongTest + @Test public void run1() throws Throwable { runTest("test", 1); } - @LongTest + @Test public void run2() throws Throwable { runTest("test", 2); } - @LongTest + @Test public void run3() throws Throwable { runTest("test", 3); } - @LongTest + @Test public void run4() throws Throwable { runTest("test", 4); } - @LongTest + @Test public void run5() throws Throwable { runTest("test", 5); } - @LongTest + @Test public void run6() throws Throwable { runTest("test", 6); } - @LongTest + @Test public void run7() throws Throwable { runTest("test", 7); } - @LongTest + @Test public void run8() throws Throwable { runTest("test", 8); } diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/reflect/Field_getType01.java --- a/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/reflect/Field_getType01.java Fri Apr 25 16:21:07 2014 +0200 +++ b/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/reflect/Field_getType01.java Mon Apr 28 11:18:15 2014 +0200 @@ -22,8 +22,9 @@ */ package com.oracle.graal.jtt.reflect; +import org.junit.*; + import com.oracle.graal.jtt.*; -import com.oracle.graal.test.*; /* */ @@ -59,47 +60,47 @@ return false; } - @LongTest + @Test public void run0() throws Throwable { runTest("test", 0); } - @LongTest + @Test public void run1() throws Throwable { runTest("test", 1); } - @LongTest + @Test public void run2() throws Throwable { runTest("test", 2); } - @LongTest + @Test public void run3() throws Throwable { runTest("test", 3); } - @LongTest + @Test public void run4() throws Throwable { runTest("test", 4); } - @LongTest + @Test public void run5() throws Throwable { runTest("test", 5); } - @LongTest + @Test public void run6() throws Throwable { runTest("test", 6); } - @LongTest + @Test public void run7() throws Throwable { runTest("test", 7); } - @LongTest + @Test public void run8() throws Throwable { runTest("test", 8); } diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/reflect/Field_set01.java --- a/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/reflect/Field_set01.java Fri Apr 25 16:21:07 2014 +0200 +++ b/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/reflect/Field_set01.java Mon Apr 28 11:18:15 2014 +0200 @@ -22,8 +22,9 @@ */ package com.oracle.graal.jtt.reflect; +import org.junit.*; + import com.oracle.graal.jtt.*; -import com.oracle.graal.test.*; /* */ @@ -67,47 +68,47 @@ return false; } - @LongTest + @Test public void run0() throws Throwable { runTest("test", 0); } - @LongTest + @Test public void run1() throws Throwable { runTest("test", 1); } - @LongTest + @Test public void run2() throws Throwable { runTest("test", 2); } - @LongTest + @Test public void run3() throws Throwable { runTest("test", 3); } - @LongTest + @Test public void run4() throws Throwable { runTest("test", 4); } - @LongTest + @Test public void run5() throws Throwable { runTest("test", 5); } - @LongTest + @Test public void run6() throws Throwable { runTest("test", 6); } - @LongTest + @Test public void run7() throws Throwable { runTest("test", 7); } - @LongTest + @Test public void run8() throws Throwable { runTest("test", 8); } diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/reflect/Field_set02.java --- a/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/reflect/Field_set02.java Fri Apr 25 16:21:07 2014 +0200 +++ b/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/reflect/Field_set02.java Mon Apr 28 11:18:15 2014 +0200 @@ -22,8 +22,9 @@ */ package com.oracle.graal.jtt.reflect; +import org.junit.*; + import com.oracle.graal.jtt.*; -import com.oracle.graal.test.*; /* */ @@ -69,47 +70,47 @@ return false; } - @LongTest + @Test public void run0() throws Throwable { runTest("test", 0); } - @LongTest + @Test public void run1() throws Throwable { runTest("test", 1); } - @LongTest + @Test public void run2() throws Throwable { runTest("test", 2); } - @LongTest + @Test public void run3() throws Throwable { runTest("test", 3); } - @LongTest + @Test public void run4() throws Throwable { runTest("test", 4); } - @LongTest + @Test public void run5() throws Throwable { runTest("test", 5); } - @LongTest + @Test public void run6() throws Throwable { runTest("test", 6); } - @LongTest + @Test public void run7() throws Throwable { runTest("test", 7); } - @LongTest + @Test public void run8() throws Throwable { runTest("test", 8); } diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/reflect/Field_set03.java --- a/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/reflect/Field_set03.java Fri Apr 25 16:21:07 2014 +0200 +++ b/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/reflect/Field_set03.java Mon Apr 28 11:18:15 2014 +0200 @@ -22,8 +22,9 @@ */ package com.oracle.graal.jtt.reflect; +import org.junit.*; + import com.oracle.graal.jtt.*; -import com.oracle.graal.test.*; /* */ @@ -69,47 +70,47 @@ return false; } - @LongTest + @Test public void run0() throws Throwable { runTest("test", 0); } - @LongTest + @Test public void run1() throws Throwable { runTest("test", 1); } - @LongTest + @Test public void run2() throws Throwable { runTest("test", 2); } - @LongTest + @Test public void run3() throws Throwable { runTest("test", 3); } - @LongTest + @Test public void run4() throws Throwable { runTest("test", 4); } - @LongTest + @Test public void run5() throws Throwable { runTest("test", 5); } - @LongTest + @Test public void run6() throws Throwable { runTest("test", 6); } - @LongTest + @Test public void run7() throws Throwable { runTest("test", 7); } - @LongTest + @Test public void run8() throws Throwable { runTest("test", 8); } diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/reflect/Invoke_except01.java --- a/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/reflect/Invoke_except01.java Fri Apr 25 16:21:07 2014 +0200 +++ b/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/reflect/Invoke_except01.java Mon Apr 28 11:18:15 2014 +0200 @@ -24,8 +24,9 @@ import java.lang.reflect.*; +import org.junit.*; + import com.oracle.graal.jtt.*; -import com.oracle.graal.test.*; /* */ @@ -56,27 +57,27 @@ return arg.length; } - @LongTest + @Test public void run0() throws Throwable { runTest("test", 0); } - @LongTest + @Test public void run1() throws Throwable { runTest("test", 1); } - @LongTest + @Test public void run2() throws Throwable { runTest("test", 2); } - @LongTest + @Test public void run3() throws Throwable { runTest("test", 3); } - @LongTest + @Test public void run4() throws Throwable { runTest("test", 4); } diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/reflect/Invoke_main01.java --- a/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/reflect/Invoke_main01.java Fri Apr 25 16:21:07 2014 +0200 +++ b/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/reflect/Invoke_main01.java Mon Apr 28 11:18:15 2014 +0200 @@ -24,8 +24,9 @@ import java.lang.reflect.*; +import org.junit.*; + import com.oracle.graal.jtt.*; -import com.oracle.graal.test.*; /* */ @@ -44,12 +45,12 @@ field = args[0]; } - @LongTest + @Test public void run0() throws Throwable { runTest("test", "test1"); } - @LongTest + @Test public void run1() throws Throwable { runTest("test", "test2"); } diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/reflect/Invoke_main03.java --- a/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/reflect/Invoke_main03.java Fri Apr 25 16:21:07 2014 +0200 +++ b/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/reflect/Invoke_main03.java Mon Apr 28 11:18:15 2014 +0200 @@ -24,8 +24,9 @@ import java.lang.reflect.*; +import org.junit.*; + import com.oracle.graal.jtt.*; -import com.oracle.graal.test.*; /* */ @@ -48,12 +49,12 @@ field = args[0]; } - @LongTest + @Test public void run0() throws Throwable { runTest("test", "test1"); } - @LongTest + @Test public void run1() throws Throwable { runTest("test", "test2"); } diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/reflect/Method_getParameterTypes01.java --- a/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/reflect/Method_getParameterTypes01.java Fri Apr 25 16:21:07 2014 +0200 +++ b/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/reflect/Method_getParameterTypes01.java Mon Apr 28 11:18:15 2014 +0200 @@ -22,8 +22,9 @@ */ package com.oracle.graal.jtt.reflect; +import org.junit.*; + import com.oracle.graal.jtt.*; -import com.oracle.graal.test.*; /* */ @@ -51,22 +52,22 @@ public void method3(int arg1, Object arg2) { } - @LongTest + @Test public void run0() throws Throwable { runTest("test", 0); } - @LongTest + @Test public void run1() throws Throwable { runTest("test", 1); } - @LongTest + @Test public void run2() throws Throwable { runTest("test", 2); } - @LongTest + @Test public void run3() throws Throwable { runTest("test", 3); } diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/reflect/Method_getReturnType01.java --- a/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/reflect/Method_getReturnType01.java Fri Apr 25 16:21:07 2014 +0200 +++ b/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/reflect/Method_getReturnType01.java Mon Apr 28 11:18:15 2014 +0200 @@ -22,8 +22,9 @@ */ package com.oracle.graal.jtt.reflect; +import org.junit.*; + import com.oracle.graal.jtt.*; -import com.oracle.graal.test.*; /* */ @@ -51,22 +52,22 @@ public void method3() { } - @LongTest + @Test public void run0() throws Throwable { runTest("test", 0); } - @LongTest + @Test public void run1() throws Throwable { runTest("test", 1); } - @LongTest + @Test public void run2() throws Throwable { runTest("test", 2); } - @LongTest + @Test public void run3() throws Throwable { runTest("test", 3); } diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/threads/Monitor_contended01.java --- a/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/threads/Monitor_contended01.java Fri Apr 25 16:21:07 2014 +0200 +++ b/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/threads/Monitor_contended01.java Mon Apr 28 11:18:15 2014 +0200 @@ -24,8 +24,9 @@ */ package com.oracle.graal.jtt.threads; +import org.junit.*; + import com.oracle.graal.jtt.*; -import com.oracle.graal.test.*; public final class Monitor_contended01 extends JTTTest implements Runnable { @@ -71,7 +72,7 @@ } } - @LongTest + @Test(timeout = 20000) public void run0() throws Throwable { runTest("test"); } diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/threads/Monitor_notowner01.java --- a/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/threads/Monitor_notowner01.java Fri Apr 25 16:21:07 2014 +0200 +++ b/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/threads/Monitor_notowner01.java Mon Apr 28 11:18:15 2014 +0200 @@ -24,8 +24,9 @@ */ package com.oracle.graal.jtt.threads; +import org.junit.*; + import com.oracle.graal.jtt.*; -import com.oracle.graal.test.*; public class Monitor_notowner01 extends JTTTest { @@ -62,7 +63,7 @@ } } - @LongTest + @Test(timeout = 20000) public void run0() throws Throwable { runTest("test"); } diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/threads/Monitorenter01.java --- a/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/threads/Monitorenter01.java Fri Apr 25 16:21:07 2014 +0200 +++ b/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/threads/Monitorenter01.java Mon Apr 28 11:18:15 2014 +0200 @@ -41,7 +41,7 @@ } } - @Test + @Test(timeout = 20000) public void run0() throws Throwable { runTest("test"); } diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/threads/Monitorenter02.java --- a/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/threads/Monitorenter02.java Fri Apr 25 16:21:07 2014 +0200 +++ b/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/threads/Monitorenter02.java Mon Apr 28 11:18:15 2014 +0200 @@ -45,7 +45,7 @@ } } - @Test + @Test(timeout = 20000) public void run0() throws Throwable { runTest("test"); } diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/threads/Object_wait01.java --- a/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/threads/Object_wait01.java Fri Apr 25 16:21:07 2014 +0200 +++ b/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/threads/Object_wait01.java Mon Apr 28 11:18:15 2014 +0200 @@ -24,8 +24,9 @@ */ package com.oracle.graal.jtt.threads; +import org.junit.*; + import com.oracle.graal.jtt.*; -import com.oracle.graal.test.*; public class Object_wait01 extends JTTTest implements Runnable { @@ -57,22 +58,22 @@ } } - @LongTest + @Test(timeout = 20000) public void run0() throws Throwable { runTest("test", 0); } - @LongTest + @Test(timeout = 20000) public void run1() throws Throwable { runTest("test", 1); } - @LongTest + @Test(timeout = 20000) public void run2() throws Throwable { runTest("test", 3); } - @LongTest + @Test(timeout = 20000) public void run3() throws Throwable { runTest("test", 15); } diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/threads/Object_wait02.java --- a/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/threads/Object_wait02.java Fri Apr 25 16:21:07 2014 +0200 +++ b/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/threads/Object_wait02.java Mon Apr 28 11:18:15 2014 +0200 @@ -24,8 +24,9 @@ */ package com.oracle.graal.jtt.threads; +import org.junit.*; + import com.oracle.graal.jtt.*; -import com.oracle.graal.test.*; public class Object_wait02 extends JTTTest implements Runnable { @@ -57,17 +58,17 @@ } } - @LongTest + @Test(timeout = 20000) public void run0() throws Throwable { runTest("test", 0); } - @LongTest + @Test(timeout = 20000) public void run1() throws Throwable { runTest("test", 1); } - @LongTest + @Test(timeout = 20000) public void run2() throws Throwable { runTest("test", 2); } diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/threads/Object_wait03.java --- a/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/threads/Object_wait03.java Fri Apr 25 16:21:07 2014 +0200 +++ b/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/threads/Object_wait03.java Mon Apr 28 11:18:15 2014 +0200 @@ -24,8 +24,9 @@ */ package com.oracle.graal.jtt.threads; +import org.junit.*; + import com.oracle.graal.jtt.*; -import com.oracle.graal.test.*; public class Object_wait03 extends JTTTest implements Runnable { @@ -63,17 +64,17 @@ } } - @LongTest + @Test(timeout = 20000) public void run0() throws Throwable { runTest("test", 0); } - @LongTest + @Test(timeout = 20000) public void run1() throws Throwable { runTest("test", 1); } - @LongTest + @Test(timeout = 20000) public void run2() throws Throwable { runTest("test", 2); } diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/threads/Object_wait04.java --- a/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/threads/Object_wait04.java Fri Apr 25 16:21:07 2014 +0200 +++ b/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/threads/Object_wait04.java Mon Apr 28 11:18:15 2014 +0200 @@ -24,8 +24,9 @@ */ package com.oracle.graal.jtt.threads; +import org.junit.*; + import com.oracle.graal.jtt.*; -import com.oracle.graal.test.*; public class Object_wait04 extends JTTTest implements Runnable { @@ -67,32 +68,32 @@ } } - @LongTest + @Test(timeout = 20000) public void run0() throws Throwable { runTest("test", 0); } - @LongTest + @Test(timeout = 20000) public void run1() throws Throwable { runTest("test", 1); } - @LongTest + @Test(timeout = 20000) public void run2() throws Throwable { runTest("test", 2); } - @LongTest + @Test(timeout = 20000) public void run3() throws Throwable { runTest("test", 3); } - @LongTest + @Test(timeout = 20000) public void run4() throws Throwable { runTest("test", 4); } - @LongTest + @Test(timeout = 20000) public void run5() throws Throwable { runTest("test", 5); } diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/threads/SynchronizedLoopExit01.java --- a/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/threads/SynchronizedLoopExit01.java Fri Apr 25 16:21:07 2014 +0200 +++ b/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/threads/SynchronizedLoopExit01.java Mon Apr 28 11:18:15 2014 +0200 @@ -30,9 +30,9 @@ /** * Inspired by {@code com.sun.media.sound.DirectAudioDevice$DirectDL.drain()}. - * + * * Two loop exits hold a monitor while merging. - * + * */ public final class SynchronizedLoopExit01 extends JTTTest { @@ -53,7 +53,7 @@ return b; } - @Test + @Test(timeout = 20000) public void run0() throws Throwable { runTest("test"); } diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/threads/ThreadLocal03.java --- a/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/threads/ThreadLocal03.java Fri Apr 25 16:21:07 2014 +0200 +++ b/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/threads/ThreadLocal03.java Mon Apr 28 11:18:15 2014 +0200 @@ -22,8 +22,9 @@ */ package com.oracle.graal.jtt.threads; +import org.junit.*; + import com.oracle.graal.jtt.*; -import com.oracle.graal.test.*; /* */ @@ -59,22 +60,22 @@ } } - @LongTest + @Test public void run0() throws Throwable { runTest("test", 0); } - @LongTest + @Test public void run1() throws Throwable { runTest("test", 1); } - @LongTest + @Test public void run2() throws Throwable { runTest("test", 2); } - @LongTest + @Test public void run3() throws Throwable { runTest("test", 3); } diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/threads/Thread_getState02.java --- a/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/threads/Thread_getState02.java Fri Apr 25 16:21:07 2014 +0200 +++ b/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/threads/Thread_getState02.java Mon Apr 28 11:18:15 2014 +0200 @@ -24,8 +24,9 @@ */ package com.oracle.graal.jtt.threads; +import org.junit.*; + import com.oracle.graal.jtt.*; -import com.oracle.graal.test.*; public final class Thread_getState02 extends JTTTest { @@ -33,7 +34,7 @@ return new Thread().getState() == Thread.State.NEW; } - @LongTest + @Test public void run0() throws Throwable { runTest("test"); } diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/threads/Thread_isInterrupted02.java --- a/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/threads/Thread_isInterrupted02.java Fri Apr 25 16:21:07 2014 +0200 +++ b/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/threads/Thread_isInterrupted02.java Mon Apr 28 11:18:15 2014 +0200 @@ -26,8 +26,9 @@ package com.oracle.graal.jtt.threads; +import org.junit.*; + import com.oracle.graal.jtt.*; -import com.oracle.graal.test.*; //Test all, mainly monitors public class Thread_isInterrupted02 extends JTTTest { @@ -85,12 +86,12 @@ } } - @LongTest + @Test(timeout = 20000) public void run0() throws Throwable { runTest("test", 0, 0); } - @LongTest + @Test(timeout = 20000) public void run1() throws Throwable { runTest("test", 1, 500); } diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/threads/Thread_isInterrupted03.java --- a/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/threads/Thread_isInterrupted03.java Fri Apr 25 16:21:07 2014 +0200 +++ b/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/threads/Thread_isInterrupted03.java Mon Apr 28 11:18:15 2014 +0200 @@ -22,8 +22,9 @@ */ package com.oracle.graal.jtt.threads; +import org.junit.*; + import com.oracle.graal.jtt.*; -import com.oracle.graal.test.*; /* */ @@ -68,7 +69,7 @@ } } - @LongTest + @Test(timeout = 20000) public void run0() throws Throwable { runTest("test"); } diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/threads/Thread_isInterrupted04.java --- a/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/threads/Thread_isInterrupted04.java Fri Apr 25 16:21:07 2014 +0200 +++ b/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/threads/Thread_isInterrupted04.java Mon Apr 28 11:18:15 2014 +0200 @@ -22,8 +22,9 @@ */ package com.oracle.graal.jtt.threads; +import org.junit.*; + import com.oracle.graal.jtt.*; -import com.oracle.graal.test.*; /* */ @@ -66,7 +67,7 @@ } - @LongTest + @Test(timeout = 20000) public void run0() throws Throwable { runTest("test"); } diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/threads/Thread_isInterrupted05.java --- a/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/threads/Thread_isInterrupted05.java Fri Apr 25 16:21:07 2014 +0200 +++ b/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/threads/Thread_isInterrupted05.java Mon Apr 28 11:18:15 2014 +0200 @@ -22,8 +22,9 @@ */ package com.oracle.graal.jtt.threads; +import org.junit.*; + import com.oracle.graal.jtt.*; -import com.oracle.graal.test.*; /* */ @@ -66,7 +67,7 @@ } } - @LongTest + @Test(timeout = 20000) public void run0() throws Throwable { runTest("test"); } diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/threads/Thread_join01.java --- a/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/threads/Thread_join01.java Fri Apr 25 16:21:07 2014 +0200 +++ b/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/threads/Thread_join01.java Mon Apr 28 11:18:15 2014 +0200 @@ -24,8 +24,9 @@ */ package com.oracle.graal.jtt.threads; +import org.junit.*; + import com.oracle.graal.jtt.*; -import com.oracle.graal.test.*; public class Thread_join01 extends JTTTest implements Runnable { @@ -43,7 +44,7 @@ cont = false; } - @LongTest + @Test(timeout = 20000) public void run0() throws Throwable { runTest("test"); } diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/threads/Thread_join02.java --- a/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/threads/Thread_join02.java Fri Apr 25 16:21:07 2014 +0200 +++ b/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/threads/Thread_join02.java Mon Apr 28 11:18:15 2014 +0200 @@ -27,8 +27,9 @@ */ package com.oracle.graal.jtt.threads; +import org.junit.*; + import com.oracle.graal.jtt.*; -import com.oracle.graal.test.*; public class Thread_join02 extends JTTTest implements Runnable { @@ -50,7 +51,7 @@ cont = false; } - @LongTest + @Test(timeout = 20000) public void run0() throws Throwable { runTest("test"); } diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/threads/Thread_join03.java --- a/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/threads/Thread_join03.java Fri Apr 25 16:21:07 2014 +0200 +++ b/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/threads/Thread_join03.java Mon Apr 28 11:18:15 2014 +0200 @@ -27,8 +27,9 @@ */ package com.oracle.graal.jtt.threads; +import org.junit.*; + import com.oracle.graal.jtt.*; -import com.oracle.graal.test.*; public class Thread_join03 extends JTTTest implements Runnable { @@ -47,7 +48,7 @@ cont = false; } - @LongTest + @Test(timeout = 20000) public void run0() throws Throwable { runTest("test"); } diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/threads/Thread_new01.java --- a/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/threads/Thread_new01.java Fri Apr 25 16:21:07 2014 +0200 +++ b/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/threads/Thread_new01.java Mon Apr 28 11:18:15 2014 +0200 @@ -24,8 +24,9 @@ */ package com.oracle.graal.jtt.threads; +import org.junit.*; + import com.oracle.graal.jtt.*; -import com.oracle.graal.test.*; public final class Thread_new01 extends JTTTest { @@ -45,27 +46,27 @@ return false; } - @LongTest + @Test public void run0() throws Throwable { runTest("test", 0); } - @LongTest + @Test public void run1() throws Throwable { runTest("test", 1); } - @LongTest + @Test public void run2() throws Throwable { runTest("test", 2); } - @LongTest + @Test public void run3() throws Throwable { runTest("test", 3); } - @LongTest + @Test public void run4() throws Throwable { runTest("test", 4); } diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/threads/Thread_new02.java --- a/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/threads/Thread_new02.java Fri Apr 25 16:21:07 2014 +0200 +++ b/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/threads/Thread_new02.java Mon Apr 28 11:18:15 2014 +0200 @@ -24,8 +24,9 @@ */ package com.oracle.graal.jtt.threads; +import org.junit.*; + import com.oracle.graal.jtt.*; -import com.oracle.graal.test.*; public class Thread_new02 extends JTTTest implements Runnable { @@ -51,27 +52,27 @@ // do nothing. } - @LongTest + @Test public void run0() throws Throwable { runTest("test", 0); } - @LongTest + @Test public void run1() throws Throwable { runTest("test", 1); } - @LongTest + @Test public void run2() throws Throwable { runTest("test", 2); } - @LongTest + @Test public void run3() throws Throwable { runTest("test", 3); } - @LongTest + @Test public void run4() throws Throwable { runTest("test", 4); } diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/threads/Thread_sleep01.java --- a/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/threads/Thread_sleep01.java Fri Apr 25 16:21:07 2014 +0200 +++ b/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/threads/Thread_sleep01.java Mon Apr 28 11:18:15 2014 +0200 @@ -24,8 +24,9 @@ */ package com.oracle.graal.jtt.threads; +import org.junit.*; + import com.oracle.graal.jtt.*; -import com.oracle.graal.test.*; public final class Thread_sleep01 extends JTTTest { @@ -35,17 +36,17 @@ return System.currentTimeMillis() - before >= i; } - @LongTest + @Test(timeout = 20000) public void run0() throws Throwable { runTest("test", 10); } - @LongTest + @Test(timeout = 20000) public void run1() throws Throwable { runTest("test", 20); } - @LongTest + @Test(timeout = 20000) public void run2() throws Throwable { runTest("test", 100); } diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/threads/Thread_yield01.java --- a/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/threads/Thread_yield01.java Fri Apr 25 16:21:07 2014 +0200 +++ b/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/threads/Thread_yield01.java Mon Apr 28 11:18:15 2014 +0200 @@ -35,7 +35,7 @@ return true; } - @Test + @Test(timeout = 20000) public void run0() throws Throwable { runTest("test"); } diff -r 3dde8d8c95b8 -r 40d0022115ee 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 Fri Apr 25 16:21:07 2014 +0200 +++ b/graal/com.oracle.graal.lir.amd64/src/com/oracle/graal/lir/amd64/AMD64Arithmetic.java Mon Apr 28 11:18:15 2014 +0200 @@ -30,7 +30,7 @@ import com.oracle.graal.asm.*; import com.oracle.graal.asm.amd64.*; import com.oracle.graal.asm.amd64.AMD64Assembler.ConditionFlag; -import com.oracle.graal.graph.*; +import com.oracle.graal.compiler.common.*; import com.oracle.graal.lir.*; import com.oracle.graal.lir.amd64.AMD64Move.MemOp; import com.oracle.graal.lir.asm.*; @@ -39,8 +39,8 @@ // @formatter:off - 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, + IADD, ISUB, IMUL, IDIV, IDIVREM, IREM, IUDIV, IUREM, IAND, IOR, IXOR, ISHL, ISHR, IUSHR, IROL, IROR, + LADD, LSUB, LMUL, LDIV, LDIVREM, LREM, LUDIV, LUREM, LAND, LOR, LXOR, LSHL, LSHR, LUSHR, LROL, LROR, FADD, FSUB, FMUL, FDIV, FREM, FAND, FOR, FXOR, DADD, DSUB, DMUL, DDIV, DREM, DAND, DOR, DXOR, INEG, LNEG, INOT, LNOT, @@ -82,6 +82,27 @@ } /** + * Unary operation with separate source and destination operand but register only. + */ + public static class Unary2RegOp extends AMD64LIRInstruction { + + @Opcode private final AMD64Arithmetic opcode; + @Def({REG}) protected AllocatableValue result; + @Use({REG}) protected AllocatableValue x; + + public Unary2RegOp(AMD64Arithmetic opcode, AllocatableValue result, AllocatableValue x) { + this.opcode = opcode; + this.result = result; + this.x = x; + } + + @Override + public void emitCode(CompilationResultBuilder crb, AMD64MacroAssembler masm) { + emit(crb, masm, opcode, result, x, null); + } + } + + /** * Unary operation with single operand for source and destination. */ public static class Unary1Op extends AMD64LIRInstruction { @@ -431,9 +452,6 @@ case LNOT: masm.notq(asLongReg(result)); break; - case L2I: - masm.andl(asIntReg(result), 0xFFFFFFFF); - break; default: throw GraalInternalError.shouldNotReachHere(); } @@ -473,6 +491,14 @@ assert asIntReg(src).equals(AMD64.rcx); masm.shrl(asIntReg(dst)); break; + case IROL: + assert asIntReg(src).equals(AMD64.rcx); + masm.roll(asIntReg(dst)); + break; + case IROR: + assert asIntReg(src).equals(AMD64.rcx); + masm.roll(asIntReg(dst)); + break; case LADD: masm.addq(asLongReg(dst), asLongReg(src)); @@ -504,6 +530,14 @@ assert asIntReg(src).equals(AMD64.rcx); masm.shrq(asLongReg(dst)); break; + case LROL: + assert asIntReg(src).equals(AMD64.rcx); + masm.rolq(asLongReg(dst)); + break; + case LROR: + assert asIntReg(src).equals(AMD64.rcx); + masm.rorq(asLongReg(dst)); + break; case FADD: masm.addss(asFloatReg(dst), asFloatReg(src)); @@ -568,6 +602,9 @@ case I2L: masm.movslq(asLongReg(dst), asIntReg(src)); break; + case L2I: + masm.movl(asIntReg(dst), asLongReg(src)); + break; case F2D: masm.cvtss2sd(asDoubleReg(dst), asFloatReg(src)); break; @@ -674,6 +711,12 @@ case IUSHR: masm.shrl(asIntReg(dst), crb.asIntConst(src) & 31); break; + case IROL: + masm.roll(asIntReg(dst), crb.asIntConst(src) & 31); + break; + case IROR: + masm.rorl(asIntReg(dst), crb.asIntConst(src) & 31); + break; case LADD: masm.addq(asLongReg(dst), crb.asIntConst(src)); @@ -702,6 +745,12 @@ case LUSHR: masm.shrq(asLongReg(dst), crb.asIntConst(src) & 63); break; + case LROL: + masm.rolq(asLongReg(dst), crb.asIntConst(src) & 31); + break; + case LROR: + masm.rorq(asLongReg(dst), crb.asIntConst(src) & 31); + break; case FADD: masm.addss(asFloatReg(dst), (AMD64Address) crb.asFloatConstRef(src)); diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.lir.amd64/src/com/oracle/graal/lir/amd64/AMD64ArrayEqualsOp.java --- a/graal/com.oracle.graal.lir.amd64/src/com/oracle/graal/lir/amd64/AMD64ArrayEqualsOp.java Fri Apr 25 16:21:07 2014 +0200 +++ b/graal/com.oracle.graal.lir.amd64/src/com/oracle/graal/lir/amd64/AMD64ArrayEqualsOp.java Mon Apr 28 11:18:15 2014 +0200 @@ -23,7 +23,7 @@ package com.oracle.graal.lir.amd64; import static com.oracle.graal.api.code.ValueUtil.*; -import static com.oracle.graal.graph.UnsafeAccess.*; +import static com.oracle.graal.compiler.common.UnsafeAccess.*; import static com.oracle.graal.lir.LIRInstruction.OperandFlag.*; import java.lang.reflect.*; @@ -38,7 +38,7 @@ import com.oracle.graal.asm.amd64.AMD64Assembler.ConditionFlag; import com.oracle.graal.lir.*; import com.oracle.graal.lir.asm.*; -import com.oracle.graal.nodes.spi.*; +import com.oracle.graal.lir.gen.*; /** * Emits code which compares two arrays of the same length. If the CPU supports any vector diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.lir.amd64/src/com/oracle/graal/lir/amd64/AMD64Compare.java --- a/graal/com.oracle.graal.lir.amd64/src/com/oracle/graal/lir/amd64/AMD64Compare.java Fri Apr 25 16:21:07 2014 +0200 +++ b/graal/com.oracle.graal.lir.amd64/src/com/oracle/graal/lir/amd64/AMD64Compare.java Mon Apr 28 11:18:15 2014 +0200 @@ -28,7 +28,7 @@ import com.oracle.graal.api.meta.*; import com.oracle.graal.asm.*; import com.oracle.graal.asm.amd64.*; -import com.oracle.graal.graph.*; +import com.oracle.graal.compiler.common.*; import com.oracle.graal.lir.*; import com.oracle.graal.lir.amd64.AMD64Move.MemOp; import com.oracle.graal.lir.asm.*; @@ -132,6 +132,9 @@ default: throw GraalInternalError.shouldNotReachHere(); } + + } else { + throw GraalInternalError.shouldNotReachHere(); } } diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.lir.amd64/src/com/oracle/graal/lir/amd64/AMD64ControlFlow.java --- a/graal/com.oracle.graal.lir.amd64/src/com/oracle/graal/lir/amd64/AMD64ControlFlow.java Fri Apr 25 16:21:07 2014 +0200 +++ b/graal/com.oracle.graal.lir.amd64/src/com/oracle/graal/lir/amd64/AMD64ControlFlow.java Mon Apr 28 11:18:15 2014 +0200 @@ -33,12 +33,12 @@ import com.oracle.graal.asm.amd64.*; import com.oracle.graal.asm.amd64.AMD64Address.Scale; import com.oracle.graal.asm.amd64.AMD64Assembler.ConditionFlag; -import com.oracle.graal.graph.*; +import com.oracle.graal.compiler.common.*; +import com.oracle.graal.compiler.common.calc.*; import com.oracle.graal.lir.*; import com.oracle.graal.lir.StandardOp.BlockEndOp; import com.oracle.graal.lir.SwitchStrategy.BaseSwitchClosure; import com.oracle.graal.lir.asm.*; -import com.oracle.graal.nodes.calc.*; public class AMD64ControlFlow { diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.lir.amd64/src/com/oracle/graal/lir/amd64/AMD64FrameMap.java --- a/graal/com.oracle.graal.lir.amd64/src/com/oracle/graal/lir/amd64/AMD64FrameMap.java Fri Apr 25 16:21:07 2014 +0200 +++ b/graal/com.oracle.graal.lir.amd64/src/com/oracle/graal/lir/amd64/AMD64FrameMap.java Mon Apr 28 11:18:15 2014 +0200 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 2014, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -24,6 +24,7 @@ import com.oracle.graal.api.code.*; import com.oracle.graal.api.meta.*; +import com.oracle.graal.asm.*; import com.oracle.graal.lir.*; /** @@ -33,7 +34,7 @@ * *

  *   Base       Contents
- *
+ * 
  *            :                                :  -----
  *   caller   | incoming overflow argument n   |    ^
  *   frame    :     ...                        :    | positive
@@ -88,8 +89,7 @@
 
     @Override
     protected int alignFrameSize(int size) {
-        int x = size + returnAddressSize() + (target.stackAlignment - 1);
-        return (x / target.stackAlignment) * target.stackAlignment - returnAddressSize();
+        return NumUtil.roundUp(size + returnAddressSize(), target.stackAlignment) - returnAddressSize();
     }
 
     @Override
diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.lir.amd64/src/com/oracle/graal/lir/amd64/AMD64MathIntrinsicOp.java
--- a/graal/com.oracle.graal.lir.amd64/src/com/oracle/graal/lir/amd64/AMD64MathIntrinsicOp.java	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.lir.amd64/src/com/oracle/graal/lir/amd64/AMD64MathIntrinsicOp.java	Mon Apr 28 11:18:15 2014 +0200
@@ -26,7 +26,7 @@
 
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.asm.amd64.*;
-import com.oracle.graal.graph.*;
+import com.oracle.graal.compiler.common.*;
 import com.oracle.graal.lir.*;
 import com.oracle.graal.lir.asm.*;
 
diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.lir.amd64/src/com/oracle/graal/lir/amd64/AMD64Move.java
--- a/graal/com.oracle.graal.lir.amd64/src/com/oracle/graal/lir/amd64/AMD64Move.java	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.lir.amd64/src/com/oracle/graal/lir/amd64/AMD64Move.java	Mon Apr 28 11:18:15 2014 +0200
@@ -33,7 +33,7 @@
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.asm.*;
 import com.oracle.graal.asm.amd64.*;
-import com.oracle.graal.graph.*;
+import com.oracle.graal.compiler.common.*;
 import com.oracle.graal.lir.*;
 import com.oracle.graal.lir.StandardOp.ImplicitNullCheck;
 import com.oracle.graal.lir.StandardOp.MoveOp;
@@ -432,6 +432,74 @@
         }
     }
 
+    @Opcode("ATOMIC_READ_AND_ADD")
+    public static class AtomicReadAndAddOp extends AMD64LIRInstruction {
+
+        private final Kind accessKind;
+
+        @Def protected AllocatableValue result;
+        @Alive({COMPOSITE}) protected AMD64AddressValue address;
+        @Use protected AllocatableValue delta;
+
+        public AtomicReadAndAddOp(Kind accessKind, AllocatableValue result, AMD64AddressValue address, AllocatableValue delta) {
+            this.accessKind = accessKind;
+            this.result = result;
+            this.address = address;
+            this.delta = delta;
+        }
+
+        @Override
+        public void emitCode(CompilationResultBuilder crb, AMD64MacroAssembler masm) {
+            move(accessKind, crb, masm, result, delta);
+            if (crb.target.isMP) {
+                masm.lock();
+            }
+            switch (accessKind) {
+                case Int:
+                    masm.xaddl(address.toAddress(), asRegister(result));
+                    break;
+                case Long:
+                    masm.xaddq(address.toAddress(), asRegister(result));
+                    break;
+                default:
+                    throw GraalInternalError.shouldNotReachHere();
+            }
+        }
+    }
+
+    @Opcode("ATOMIC_READ_AND_WRITE")
+    public static class AtomicReadAndWriteOp extends AMD64LIRInstruction {
+
+        private final Kind accessKind;
+
+        @Def protected AllocatableValue result;
+        @Alive({COMPOSITE}) protected AMD64AddressValue address;
+        @Use protected AllocatableValue newValue;
+
+        public AtomicReadAndWriteOp(Kind accessKind, AllocatableValue result, AMD64AddressValue address, AllocatableValue newValue) {
+            this.accessKind = accessKind;
+            this.result = result;
+            this.address = address;
+            this.newValue = newValue;
+        }
+
+        @Override
+        public void emitCode(CompilationResultBuilder crb, AMD64MacroAssembler masm) {
+            move(accessKind, crb, masm, result, newValue);
+            switch (accessKind) {
+                case Int:
+                    masm.xchgl(asRegister(result), address.toAddress());
+                    break;
+                case Long:
+                case Object:
+                    masm.xchgq(asRegister(result), address.toAddress());
+                    break;
+                default:
+                    throw GraalInternalError.shouldNotReachHere();
+            }
+        }
+    }
+
     public static void move(CompilationResultBuilder crb, AMD64MacroAssembler masm, Value result, Value input) {
         move(result.getKind(), crb, masm, result, input);
     }
diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.lir.amd64/src/com/oracle/graal/lir/amd64/AMD64TestMemoryOp.java
--- a/graal/com.oracle.graal.lir.amd64/src/com/oracle/graal/lir/amd64/AMD64TestMemoryOp.java	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.lir.amd64/src/com/oracle/graal/lir/amd64/AMD64TestMemoryOp.java	Mon Apr 28 11:18:15 2014 +0200
@@ -27,7 +27,7 @@
 
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.asm.amd64.*;
-import com.oracle.graal.graph.*;
+import com.oracle.graal.compiler.common.*;
 import com.oracle.graal.lir.*;
 import com.oracle.graal.lir.amd64.AMD64Move.MemOp;
 import com.oracle.graal.lir.asm.*;
diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.lir.amd64/src/com/oracle/graal/lir/amd64/AMD64TestOp.java
--- a/graal/com.oracle.graal.lir.amd64/src/com/oracle/graal/lir/amd64/AMD64TestOp.java	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.lir.amd64/src/com/oracle/graal/lir/amd64/AMD64TestOp.java	Mon Apr 28 11:18:15 2014 +0200
@@ -27,7 +27,7 @@
 
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.asm.amd64.*;
-import com.oracle.graal.graph.*;
+import com.oracle.graal.compiler.common.*;
 import com.oracle.graal.lir.asm.*;
 
 public class AMD64TestOp extends AMD64LIRInstruction {
diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.lir.hsail/src/com/oracle/graal/lir/hsail/HSAILArithmetic.java
--- a/graal/com.oracle.graal.lir.hsail/src/com/oracle/graal/lir/hsail/HSAILArithmetic.java	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.lir.hsail/src/com/oracle/graal/lir/hsail/HSAILArithmetic.java	Mon Apr 28 11:18:15 2014 +0200
@@ -27,7 +27,7 @@
 
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.asm.hsail.*;
-import com.oracle.graal.graph.*;
+import com.oracle.graal.compiler.common.*;
 import com.oracle.graal.lir.*;
 import com.oracle.graal.lir.asm.*;
 
diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.lir.hsail/src/com/oracle/graal/lir/hsail/HSAILBitManipulationOp.java
--- a/graal/com.oracle.graal.lir.hsail/src/com/oracle/graal/lir/hsail/HSAILBitManipulationOp.java	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.lir.hsail/src/com/oracle/graal/lir/hsail/HSAILBitManipulationOp.java	Mon Apr 28 11:18:15 2014 +0200
@@ -24,7 +24,7 @@
 
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.asm.hsail.*;
-import com.oracle.graal.graph.*;
+import com.oracle.graal.compiler.common.*;
 import com.oracle.graal.lir.*;
 import com.oracle.graal.lir.asm.*;
 
diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.lir.hsail/src/com/oracle/graal/lir/hsail/HSAILCompare.java
--- a/graal/com.oracle.graal.lir.hsail/src/com/oracle/graal/lir/hsail/HSAILCompare.java	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.lir.hsail/src/com/oracle/graal/lir/hsail/HSAILCompare.java	Mon Apr 28 11:18:15 2014 +0200
@@ -26,10 +26,10 @@
 
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.asm.hsail.*;
-import com.oracle.graal.graph.*;
+import com.oracle.graal.compiler.common.*;
+import com.oracle.graal.compiler.common.calc.*;
 import com.oracle.graal.lir.*;
 import com.oracle.graal.lir.asm.*;
-import com.oracle.graal.nodes.calc.*;
 
 /**
  * Implementation of compare operations.
diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.lir.hsail/src/com/oracle/graal/lir/hsail/HSAILControlFlow.java
--- a/graal/com.oracle.graal.lir.hsail/src/com/oracle/graal/lir/hsail/HSAILControlFlow.java	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.lir.hsail/src/com/oracle/graal/lir/hsail/HSAILControlFlow.java	Mon Apr 28 11:18:15 2014 +0200
@@ -29,13 +29,13 @@
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.asm.*;
 import com.oracle.graal.asm.hsail.*;
-import com.oracle.graal.graph.*;
+import com.oracle.graal.compiler.common.*;
+import com.oracle.graal.compiler.common.calc.*;
 import com.oracle.graal.hsail.*;
 import com.oracle.graal.lir.*;
 import com.oracle.graal.lir.StandardOp.BlockEndOp;
 import com.oracle.graal.lir.SwitchStrategy.BaseSwitchClosure;
 import com.oracle.graal.lir.asm.*;
-import com.oracle.graal.nodes.calc.*;
 
 /**
  * Implementation of control flow instructions.
@@ -129,11 +129,17 @@
         }
     }
 
+    public interface DeoptimizingOp {
+        public LIRFrameState getFrameState();
+
+        public int getCodeBufferPos();
+    }
+
     /***
      * The ALIVE annotation is so we can get a scratch32 register that does not clobber
      * actionAndReason.
      */
-    public static class DeoptimizeOp extends ReturnOp {
+    public static class DeoptimizeOp extends ReturnOp implements DeoptimizingOp {
 
         @Alive({REG, CONST}) protected Value actionAndReason;
         @State protected LIRFrameState frameState;
@@ -173,6 +179,8 @@
             // debugInfo)
             codeBufferPos = masm.position();
 
+            masm.emitComment("/* HSAIL Deoptimization pos=" + codeBufferPos + ", bci=" + frameState.debugInfo().getBytecodePosition().getBCI() + ", frameState=" + frameState + " */");
+
             // get the bitmap of $d regs that contain references
             ReferenceMap referenceMap = frameState.debugInfo().getReferenceMap();
             for (int dreg = HSAIL.d0.number; dreg <= HSAIL.d15.number; dreg++) {
@@ -181,14 +189,9 @@
                 }
             }
 
-            // here we will by convention use some never-allocated registers to pass to the epilogue
-            // deopt code
-            // todo: define these in HSAIL.java
-            // we need to pass the actionAndReason and the codeBufferPos
-
-            AllocatableValue actionAndReasonReg = HSAIL.s32.asValue(Kind.Int);
-            AllocatableValue codeBufferOffsetReg = HSAIL.s33.asValue(Kind.Int);
-            AllocatableValue dregOopMapReg = HSAIL.s39.asValue(Kind.Int);
+            AllocatableValue actionAndReasonReg = HSAIL.actionAndReasonReg.asValue(Kind.Int);
+            AllocatableValue codeBufferOffsetReg = HSAIL.codeBufferOffsetReg.asValue(Kind.Int);
+            AllocatableValue dregOopMapReg = HSAIL.dregOopMapReg.asValue(Kind.Int);
             masm.emitMov(Kind.Int, actionAndReasonReg, actionAndReason);
             masm.emitMov(Kind.Int, codeBufferOffsetReg, Constant.forInt(codeBufferPos));
             masm.emitMov(Kind.Int, dregOopMapReg, Constant.forInt(dregOopMap));
diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.lir.hsail/src/com/oracle/graal/lir/hsail/HSAILMove.java
--- a/graal/com.oracle.graal.lir.hsail/src/com/oracle/graal/lir/hsail/HSAILMove.java	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.lir.hsail/src/com/oracle/graal/lir/hsail/HSAILMove.java	Mon Apr 28 11:18:15 2014 +0200
@@ -28,8 +28,8 @@
 import com.oracle.graal.api.code.*;
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.asm.hsail.*;
+import com.oracle.graal.compiler.common.*;
 import com.oracle.graal.debug.*;
-import com.oracle.graal.graph.*;
 import com.oracle.graal.lir.*;
 import com.oracle.graal.lir.StandardOp.MoveOp;
 import com.oracle.graal.lir.asm.*;
@@ -95,6 +95,13 @@
             super(moveKind);
             this.result = result;
             this.input = input;
+            checkForNullObjectInput();
+        }
+
+        private void checkForNullObjectInput() {
+            if (result.getKind() == Kind.Object && isConstant(input) && input.getKind() == Kind.Long && ((Constant) input).asLong() == 0) {
+                input = Constant.NULL_OBJECT;
+            }
         }
 
         @Override
@@ -440,6 +447,65 @@
         }
     }
 
+    @Opcode("ATOMIC_READ_AND_ADD")
+    public static class AtomicReadAndAddOp extends HSAILLIRInstruction {
+
+        private final Kind accessKind;
+
+        @Def protected AllocatableValue result;
+        @Use({COMPOSITE}) protected HSAILAddressValue address;
+        @Use({REG, CONST}) protected Value delta;
+
+        public AtomicReadAndAddOp(Kind accessKind, AllocatableValue result, HSAILAddressValue address, Value delta) {
+            this.accessKind = accessKind;
+            this.result = result;
+            this.address = address;
+            this.delta = delta;
+        }
+
+        public HSAILAddressValue getAddress() {
+            return address;
+        }
+
+        @Override
+        public void emitCode(CompilationResultBuilder crb, HSAILAssembler masm) {
+            switch (accessKind) {
+                case Int:
+                case Long:
+                    masm.emitAtomicAdd(result, address.toAddress(), delta);
+                    break;
+                default:
+                    throw GraalInternalError.shouldNotReachHere();
+            }
+        }
+    }
+
+    @Opcode("ATOMIC_READ_AND_WRITE")
+    public static class AtomicReadAndWriteOp extends HSAILLIRInstruction {
+
+        private final Kind accessKind;
+
+        @Def protected AllocatableValue result;
+        @Use({COMPOSITE}) protected HSAILAddressValue address;
+        @Use({REG, CONST}) protected Value newValue;
+
+        public AtomicReadAndWriteOp(Kind accessKind, AllocatableValue result, HSAILAddressValue address, Value newValue) {
+            this.accessKind = accessKind;
+            this.result = result;
+            this.address = address;
+            this.newValue = newValue;
+        }
+
+        public HSAILAddressValue getAddress() {
+            return address;
+        }
+
+        @Override
+        public void emitCode(CompilationResultBuilder crb, HSAILAssembler masm) {
+            masm.emitAtomicExch(accessKind, result, address.toAddress(), newValue);
+        }
+    }
+
     public static class NullCheckOp extends HSAILLIRInstruction {
 
         @Use protected Value input;
@@ -482,4 +548,5 @@
             throw GraalInternalError.shouldNotReachHere();
         }
     }
+
 }
diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.lir.ptx/src/com/oracle/graal/lir/ptx/PTXArithmetic.java
--- a/graal/com.oracle.graal.lir.ptx/src/com/oracle/graal/lir/ptx/PTXArithmetic.java	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.lir.ptx/src/com/oracle/graal/lir/ptx/PTXArithmetic.java	Mon Apr 28 11:18:15 2014 +0200
@@ -42,7 +42,7 @@
 import com.oracle.graal.asm.ptx.PTXMacroAssembler.Sub;
 import com.oracle.graal.asm.ptx.PTXMacroAssembler.Ushr;
 import com.oracle.graal.asm.ptx.PTXMacroAssembler.Xor;
-import com.oracle.graal.graph.*;
+import com.oracle.graal.compiler.common.*;
 import com.oracle.graal.lir.*;
 import com.oracle.graal.lir.asm.*;
 
diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.lir.ptx/src/com/oracle/graal/lir/ptx/PTXBitManipulationOp.java
--- a/graal/com.oracle.graal.lir.ptx/src/com/oracle/graal/lir/ptx/PTXBitManipulationOp.java	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.lir.ptx/src/com/oracle/graal/lir/ptx/PTXBitManipulationOp.java	Mon Apr 28 11:18:15 2014 +0200
@@ -25,7 +25,7 @@
 import com.oracle.graal.api.code.*;
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.asm.ptx.*;
-import com.oracle.graal.graph.*;
+import com.oracle.graal.compiler.common.*;
 import com.oracle.graal.lir.*;
 import com.oracle.graal.lir.asm.*;
 
diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.lir.ptx/src/com/oracle/graal/lir/ptx/PTXCompare.java
--- a/graal/com.oracle.graal.lir.ptx/src/com/oracle/graal/lir/ptx/PTXCompare.java	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.lir.ptx/src/com/oracle/graal/lir/ptx/PTXCompare.java	Mon Apr 28 11:18:15 2014 +0200
@@ -28,10 +28,10 @@
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.asm.ptx.*;
 import com.oracle.graal.asm.ptx.PTXAssembler.Setp;
-import com.oracle.graal.graph.*;
+import com.oracle.graal.compiler.common.*;
+import com.oracle.graal.compiler.common.calc.*;
 import com.oracle.graal.lir.*;
 import com.oracle.graal.lir.asm.*;
-import com.oracle.graal.nodes.calc.*;
 
 public enum PTXCompare {
     ICMP,
diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.lir.ptx/src/com/oracle/graal/lir/ptx/PTXControlFlow.java
--- a/graal/com.oracle.graal.lir.ptx/src/com/oracle/graal/lir/ptx/PTXControlFlow.java	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.lir.ptx/src/com/oracle/graal/lir/ptx/PTXControlFlow.java	Mon Apr 28 11:18:15 2014 +0200
@@ -22,9 +22,9 @@
  */
 package com.oracle.graal.lir.ptx;
 
+import static com.oracle.graal.compiler.common.calc.Condition.*;
 import static com.oracle.graal.lir.LIRInstruction.OperandFlag.*;
 import static com.oracle.graal.lir.LIRValueUtil.*;
-import static com.oracle.graal.nodes.calc.Condition.*;
 
 import com.oracle.graal.api.code.CompilationResult.JumpTable;
 import com.oracle.graal.api.meta.*;
@@ -33,15 +33,27 @@
 import com.oracle.graal.asm.ptx.PTXAssembler.Setp;
 import com.oracle.graal.asm.ptx.*;
 import com.oracle.graal.asm.ptx.PTXMacroAssembler.Mov;
-import com.oracle.graal.graph.*;
+import com.oracle.graal.compiler.common.*;
+import com.oracle.graal.compiler.common.calc.*;
 import com.oracle.graal.lir.*;
 import com.oracle.graal.lir.StandardOp.BlockEndOp;
 import com.oracle.graal.lir.SwitchStrategy.BaseSwitchClosure;
 import com.oracle.graal.lir.asm.*;
-import com.oracle.graal.nodes.calc.*;
 
 public class PTXControlFlow {
 
+    public static abstract class PTXPredicatedLIRInstruction extends PTXLIRInstruction {
+        private int predRegNum;
+
+        PTXPredicatedLIRInstruction(int regNum) {
+            predRegNum = regNum;
+        }
+
+        public int getPredRegNum() {
+            return predRegNum;
+        }
+    }
+
     public static class ReturnOp extends PTXLIRInstruction {
 
         @Use({REG, ILLEGAL}) protected Value x;
@@ -69,26 +81,25 @@
         }
     }
 
-    public static class BranchOp extends PTXLIRInstruction implements StandardOp.BranchOp {
+    public static class BranchOp extends PTXPredicatedLIRInstruction implements StandardOp.BranchOp {
 
         protected final Condition condition;
         protected final LabelRef trueDestination;
         protected final LabelRef falseDestination;
-        protected int predRegNum;
 
         public BranchOp(Condition condition, LabelRef trueDestination, LabelRef falseDestination, int predReg) {
+            super(predReg);
             this.condition = condition;
             this.trueDestination = trueDestination;
             this.falseDestination = falseDestination;
-            this.predRegNum = predReg;
         }
 
         @Override
         public void emitCode(CompilationResultBuilder crb, PTXMacroAssembler masm) {
             if (crb.isSuccessorEdge(trueDestination)) {
-                masm.bra(masm.nameOf(falseDestination.label()), predRegNum, false);
+                masm.bra(masm.nameOf(falseDestination.label()), getPredRegNum(), false);
             } else {
-                masm.bra(masm.nameOf(trueDestination.label()), predRegNum, true);
+                masm.bra(masm.nameOf(trueDestination.label()), getPredRegNum(), true);
                 if (!crb.isSuccessorEdge(falseDestination)) {
                     masm.jmp(falseDestination.label());
                 }
@@ -96,49 +107,47 @@
         }
     }
 
-    public static class CondMoveOp extends PTXLIRInstruction {
+    public static class CondMoveOp extends PTXPredicatedLIRInstruction {
 
         @Def({REG, HINT}) protected Value result;
         @Alive({REG}) protected Value trueValue;
         @Use({REG, STACK, CONST}) protected Value falseValue;
         private final Condition condition;
-        private final int predicate;
 
         public CondMoveOp(Variable result, Condition condition, Variable trueValue, Value falseValue, int predicateRegister) {
+            super(predicateRegister);
             this.result = result;
             this.condition = condition;
             this.trueValue = trueValue;
             this.falseValue = falseValue;
-            this.predicate = predicateRegister;
         }
 
         @Override
         public void emitCode(CompilationResultBuilder crb, PTXMacroAssembler masm) {
-            cmove(crb, masm, result, false, condition, false, trueValue, falseValue, predicate);
+            cmove(crb, masm, result, false, condition, false, trueValue, falseValue, getPredRegNum());
         }
     }
 
-    public static class FloatCondMoveOp extends PTXLIRInstruction {
+    public static class FloatCondMoveOp extends PTXPredicatedLIRInstruction {
 
         @Def({REG}) protected Value result;
         @Alive({REG}) protected Value trueValue;
         @Alive({REG}) protected Value falseValue;
         private final Condition condition;
         private final boolean unorderedIsTrue;
-        private final int predicate;
 
         public FloatCondMoveOp(Variable result, Condition condition, boolean unorderedIsTrue, Variable trueValue, Variable falseValue, int predicateRegister) {
+            super(predicateRegister);
             this.result = result;
             this.condition = condition;
             this.unorderedIsTrue = unorderedIsTrue;
             this.trueValue = trueValue;
             this.falseValue = falseValue;
-            this.predicate = predicateRegister;
         }
 
         @Override
         public void emitCode(CompilationResultBuilder crb, PTXMacroAssembler masm) {
-            cmove(crb, masm, result, true, condition, unorderedIsTrue, trueValue, falseValue, predicate);
+            cmove(crb, masm, result, true, condition, unorderedIsTrue, trueValue, falseValue, getPredRegNum());
         }
     }
 
@@ -193,7 +202,7 @@
         }
     }
 
-    public static class StrategySwitchOp extends PTXLIRInstruction implements BlockEndOp {
+    public static class StrategySwitchOp extends PTXPredicatedLIRInstruction implements BlockEndOp {
 
         @Use({CONST}) protected Constant[] keyConstants;
         private final LabelRef[] keyTargets;
@@ -201,10 +210,9 @@
         @Alive({REG}) protected Value key;
         @Temp({REG, ILLEGAL}) protected Value scratch;
         private final SwitchStrategy strategy;
-        // Number of predicate register that would be set by this instruction.
-        protected int predRegNum;
 
         public StrategySwitchOp(SwitchStrategy strategy, LabelRef[] keyTargets, LabelRef defaultTarget, Value key, Value scratch, int predReg) {
+            super(predReg);
             this.strategy = strategy;
             this.keyConstants = strategy.keyConstants;
             this.keyTargets = keyTargets;
@@ -214,7 +222,6 @@
             assert keyConstants.length == keyTargets.length;
             assert keyConstants.length == strategy.keyProbabilities.length;
             assert (scratch.getKind() == Kind.Illegal) == (key.getKind() == Kind.Int || key.getKind() == Kind.Long);
-            predRegNum = predReg;
         }
 
         @Override
@@ -228,40 +235,38 @@
                             if (crb.codeCache.needsDataPatch(keyConstants[index])) {
                                 crb.recordInlineDataInCode(keyConstants[index]);
                             }
-                            new Setp(EQ, keyConstants[index], key, predRegNum).emit(masm);
+                            new Setp(EQ, keyConstants[index], key, getPredRegNum()).emit(masm);
                             break;
                         case Object:
                             assert condition == Condition.EQ || condition == Condition.NE;
                             PTXMove.move(crb, masm, scratch, keyConstants[index]);
-                            new Setp(condition, scratch, key, predRegNum).emit(masm);
+                            new Setp(condition, scratch, key, getPredRegNum()).emit(masm);
                             break;
                         default:
                             throw new GraalInternalError("switch only supported for int, long and object");
                     }
-                    masm.bra(masm.nameOf(target), predRegNum, true);
+                    masm.bra(masm.nameOf(target), getPredRegNum(), true);
                 }
             };
             strategy.run(closure);
         }
     }
 
-    public static class TableSwitchOp extends PTXLIRInstruction implements BlockEndOp {
+    public static class TableSwitchOp extends PTXPredicatedLIRInstruction implements BlockEndOp {
 
         private final int lowKey;
         private final LabelRef defaultTarget;
         private final LabelRef[] targets;
         @Alive protected Value index;
         @Temp protected Value scratch;
-        // Number of predicate register that would be set by this instruction.
-        protected int predRegNum;
 
         public TableSwitchOp(final int lowKey, final LabelRef defaultTarget, final LabelRef[] targets, Variable index, Variable scratch, int predReg) {
+            super(predReg);
             this.lowKey = lowKey;
             this.defaultTarget = defaultTarget;
             this.targets = targets;
             this.index = index;
             this.scratch = scratch;
-            predRegNum = predReg;
         }
 
         @Override
@@ -272,14 +277,14 @@
             if (lowKey != 0) {
                 // subtract the low value from the switch value
                 // new Sub(value, value, lowKey).emit(masm);
-                new Setp(GT, index, Constant.forInt(highKey - lowKey), predRegNum).emit(masm);
+                new Setp(GT, index, Constant.forInt(highKey - lowKey), getPredRegNum()).emit(masm);
             } else {
-                new Setp(GT, index, Constant.forInt(highKey), predRegNum).emit(masm);
+                new Setp(GT, index, Constant.forInt(highKey), getPredRegNum()).emit(masm);
             }
 
             // Jump to default target if index is not within the jump table
             if (defaultTarget != null) {
-                masm.bra(masm.nameOf(defaultTarget.label()), predRegNum, true);
+                masm.bra(masm.nameOf(defaultTarget.label()), getPredRegNum(), true);
             }
 
             // address of jump table
diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.lir.ptx/src/com/oracle/graal/lir/ptx/PTXMemOp.java
--- a/graal/com.oracle.graal.lir.ptx/src/com/oracle/graal/lir/ptx/PTXMemOp.java	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.lir.ptx/src/com/oracle/graal/lir/ptx/PTXMemOp.java	Mon Apr 28 11:18:15 2014 +0200
@@ -31,7 +31,7 @@
 import com.oracle.graal.asm.ptx.PTXMacroAssembler.LoadAddr;
 import com.oracle.graal.asm.ptx.PTXMacroAssembler.LoadParam;
 import com.oracle.graal.asm.ptx.PTXMacroAssembler.St;
-import com.oracle.graal.graph.*;
+import com.oracle.graal.compiler.common.*;
 import com.oracle.graal.lir.*;
 import com.oracle.graal.lir.asm.*;
 
diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.lir.ptx/src/com/oracle/graal/lir/ptx/PTXMove.java
--- a/graal/com.oracle.graal.lir.ptx/src/com/oracle/graal/lir/ptx/PTXMove.java	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.lir.ptx/src/com/oracle/graal/lir/ptx/PTXMove.java	Mon Apr 28 11:18:15 2014 +0200
@@ -30,7 +30,7 @@
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.asm.ptx.*;
 import com.oracle.graal.asm.ptx.PTXMacroAssembler.Mov;
-import com.oracle.graal.graph.*;
+import com.oracle.graal.compiler.common.*;
 import com.oracle.graal.lir.*;
 import com.oracle.graal.lir.StandardOp.MoveOp;
 import com.oracle.graal.lir.StandardOp.NullCheck;
diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.lir.ptx/src/com/oracle/graal/lir/ptx/PTXTestOp.java
--- a/graal/com.oracle.graal.lir.ptx/src/com/oracle/graal/lir/ptx/PTXTestOp.java	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.lir.ptx/src/com/oracle/graal/lir/ptx/PTXTestOp.java	Mon Apr 28 11:18:15 2014 +0200
@@ -28,8 +28,8 @@
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.asm.ptx.*;
 import com.oracle.graal.asm.ptx.PTXAssembler.Setp;
+import com.oracle.graal.compiler.common.calc.*;
 import com.oracle.graal.lir.asm.*;
-import com.oracle.graal.nodes.calc.*;
 
 public class PTXTestOp extends PTXLIRInstruction {
 
diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.lir.sparc/src/com/oracle/graal/lir/sparc/SPARCArithmetic.java
--- a/graal/com.oracle.graal.lir.sparc/src/com/oracle/graal/lir/sparc/SPARCArithmetic.java	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.lir.sparc/src/com/oracle/graal/lir/sparc/SPARCArithmetic.java	Mon Apr 28 11:18:15 2014 +0200
@@ -56,10 +56,10 @@
 import com.oracle.graal.asm.sparc.SPARCMacroAssembler.Neg;
 import com.oracle.graal.asm.sparc.SPARCMacroAssembler.Not;
 import com.oracle.graal.asm.sparc.SPARCMacroAssembler.Signx;
-import com.oracle.graal.graph.*;
+import com.oracle.graal.compiler.common.*;
 import com.oracle.graal.lir.*;
 import com.oracle.graal.lir.asm.*;
-import com.oracle.graal.nodes.spi.*;
+import com.oracle.graal.lir.gen.*;
 
 public enum SPARCArithmetic {
     // @formatter:off
@@ -68,7 +68,7 @@
     FADD, FSUB, FMUL, FDIV, FREM, FAND, FOR, FXOR,
     DADD, DSUB, DMUL, DDIV, DREM, DAND, DOR, DXOR,
     INEG, LNEG, FNEG, DNEG, INOT, LNOT,
-    I2L, L2I, I2B, I2C, I2S,
+    L2I, B2I, S2I, B2L, S2L, I2L,
     F2D, D2F,
     I2F, I2D, F2I, D2I,
     L2F, L2D, F2L, D2L,
@@ -572,11 +572,11 @@
                 case L2I:
                     new Signx(asLongReg(src), asIntReg(dst)).emit(masm);
                     break;
-                case I2B:
+                case B2I:
                     new Sll(asIntReg(src), 24, asIntReg(dst)).emit(masm);
                     new Srl(asIntReg(dst), 24, asIntReg(dst)).emit(masm);
                     break;
-                case I2C:
+                case S2I:
                     new Sll(asIntReg(src), 16, asIntReg(dst)).emit(masm);
                     new Srl(asIntReg(dst), 16, asIntReg(dst)).emit(masm);
                     break;
diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.lir.sparc/src/com/oracle/graal/lir/sparc/SPARCBitManipulationOp.java
--- a/graal/com.oracle.graal.lir.sparc/src/com/oracle/graal/lir/sparc/SPARCBitManipulationOp.java	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.lir.sparc/src/com/oracle/graal/lir/sparc/SPARCBitManipulationOp.java	Mon Apr 28 11:18:15 2014 +0200
@@ -37,10 +37,10 @@
 import com.oracle.graal.asm.sparc.SPARCAssembler.Sub;
 import com.oracle.graal.asm.sparc.*;
 import com.oracle.graal.asm.sparc.SPARCMacroAssembler.Mov;
-import com.oracle.graal.graph.*;
+import com.oracle.graal.compiler.common.*;
 import com.oracle.graal.lir.*;
 import com.oracle.graal.lir.asm.*;
-import com.oracle.graal.nodes.spi.*;
+import com.oracle.graal.lir.gen.*;
 
 public class SPARCBitManipulationOp extends SPARCLIRInstruction {
 
diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.lir.sparc/src/com/oracle/graal/lir/sparc/SPARCByteSwapOp.java
--- a/graal/com.oracle.graal.lir.sparc/src/com/oracle/graal/lir/sparc/SPARCByteSwapOp.java	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.lir.sparc/src/com/oracle/graal/lir/sparc/SPARCByteSwapOp.java	Mon Apr 28 11:18:15 2014 +0200
@@ -24,7 +24,7 @@
 
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.asm.sparc.*;
-import com.oracle.graal.graph.*;
+import com.oracle.graal.compiler.common.*;
 import com.oracle.graal.lir.*;
 import com.oracle.graal.lir.asm.*;
 
diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.lir.sparc/src/com/oracle/graal/lir/sparc/SPARCCompare.java
--- a/graal/com.oracle.graal.lir.sparc/src/com/oracle/graal/lir/sparc/SPARCCompare.java	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.lir.sparc/src/com/oracle/graal/lir/sparc/SPARCCompare.java	Mon Apr 28 11:18:15 2014 +0200
@@ -29,7 +29,7 @@
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.asm.sparc.*;
 import com.oracle.graal.asm.sparc.SPARCMacroAssembler.Cmp;
-import com.oracle.graal.graph.*;
+import com.oracle.graal.compiler.common.*;
 import com.oracle.graal.lir.*;
 import com.oracle.graal.lir.asm.*;
 
diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.lir.sparc/src/com/oracle/graal/lir/sparc/SPARCControlFlow.java
--- a/graal/com.oracle.graal.lir.sparc/src/com/oracle/graal/lir/sparc/SPARCControlFlow.java	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.lir.sparc/src/com/oracle/graal/lir/sparc/SPARCControlFlow.java	Mon Apr 28 11:18:15 2014 +0200
@@ -48,12 +48,12 @@
 import com.oracle.graal.asm.sparc.SPARCMacroAssembler.Jmp;
 import com.oracle.graal.asm.sparc.SPARCMacroAssembler.Nop;
 import com.oracle.graal.asm.sparc.SPARCMacroAssembler.Ret;
-import com.oracle.graal.graph.*;
+import com.oracle.graal.compiler.common.*;
+import com.oracle.graal.compiler.common.calc.*;
 import com.oracle.graal.lir.*;
 import com.oracle.graal.lir.StandardOp.BlockEndOp;
 import com.oracle.graal.lir.SwitchStrategy.BaseSwitchClosure;
 import com.oracle.graal.lir.asm.*;
-import com.oracle.graal.nodes.calc.*;
 
 public class SPARCControlFlow {
 
@@ -270,13 +270,16 @@
     @Opcode("CMOVE")
     public static class CondMoveOp extends SPARCLIRInstruction {
 
+        private final Kind kind;
+
         @Def({REG, HINT}) protected Value result;
         @Alive({REG}) protected Value trueValue;
         @Use({REG, STACK, CONST}) protected Value falseValue;
 
         private final ConditionFlag condition;
 
-        public CondMoveOp(Variable result, Condition condition, Variable trueValue, Value falseValue) {
+        public CondMoveOp(Kind kind, Variable result, Condition condition, Variable trueValue, Value falseValue) {
+            this.kind = kind;
             this.result = result;
             this.condition = intCond(condition);
             this.trueValue = trueValue;
@@ -285,20 +288,28 @@
 
         @Override
         public void emitCode(CompilationResultBuilder crb, SPARCMacroAssembler masm) {
-            cmove(crb, masm, result, false, condition, false, trueValue, falseValue);
+            // check that we don't overwrite an input operand before it is used.
+            assert !result.equals(trueValue);
+
+            SPARCMove.move(crb, masm, result, falseValue);
+            cmove(crb, masm, kind, result, condition, trueValue);
         }
     }
 
     @Opcode("CMOVE")
     public static class FloatCondMoveOp extends SPARCLIRInstruction {
 
+        private final Kind kind;
+
         @Def({REG}) protected Value result;
         @Alive({REG}) protected Value trueValue;
         @Alive({REG}) protected Value falseValue;
+
         private final ConditionFlag condition;
         private final boolean unorderedIsTrue;
 
-        public FloatCondMoveOp(Variable result, Condition condition, boolean unorderedIsTrue, Variable trueValue, Variable falseValue) {
+        public FloatCondMoveOp(Kind kind, Variable result, Condition condition, boolean unorderedIsTrue, Variable trueValue, Variable falseValue) {
+            this.kind = kind;
             this.result = result;
             this.condition = floatCond(condition);
             this.unorderedIsTrue = unorderedIsTrue;
@@ -308,18 +319,12 @@
 
         @Override
         public void emitCode(CompilationResultBuilder crb, SPARCMacroAssembler masm) {
-            cmove(crb, masm, result, true, condition, unorderedIsTrue, trueValue, falseValue);
-        }
-    }
+            // check that we don't overwrite an input operand before it is used.
+            assert !result.equals(trueValue);
 
-    private static void cmove(CompilationResultBuilder crb, SPARCMacroAssembler masm, Value result, boolean isFloat, ConditionFlag condition, boolean unorderedIsTrue, Value trueValue, Value falseValue) {
-        // check that we don't overwrite an input operand before it is used.
-        assert !result.equals(trueValue);
+            SPARCMove.move(crb, masm, result, falseValue);
+            cmove(crb, masm, kind, result, condition, trueValue);
 
-        SPARCMove.move(crb, masm, result, falseValue);
-        cmove(crb, masm, result, condition, trueValue);
-
-        if (isFloat) {
             if (unorderedIsTrue && !trueOnUnordered(condition)) {
                 // cmove(crb, masm, result, ConditionFlag.Parity, trueValue);
                 throw GraalInternalError.unimplemented();
@@ -330,18 +335,20 @@
         }
     }
 
-    private static void cmove(CompilationResultBuilder crb, SPARCMacroAssembler masm, Value result, ConditionFlag cond, Value other) {
+    private static void cmove(CompilationResultBuilder crb, SPARCMacroAssembler masm, Kind kind, Value result, ConditionFlag cond, Value other) {
         if (!isRegister(other)) {
             SPARCMove.move(crb, masm, result, other);
-            throw new InternalError("result should be scratch");
+            throw GraalInternalError.shouldNotReachHere("result should be scratch");
         }
         assert !asRegister(other).equals(asRegister(result)) : "other already overwritten by previous move";
-        switch (other.getKind()) {
+        switch (kind) {
             case Int:
-                // XXX CC depends on compare
                 new Movcc(cond, CC.Icc, asRegister(other), asRegister(result)).emit(masm);
                 break;
             case Long:
+            case Object:
+                new Movcc(cond, CC.Xcc, asRegister(other), asRegister(result)).emit(masm);
+                break;
             default:
                 throw GraalInternalError.shouldNotReachHere();
         }
diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.lir.sparc/src/com/oracle/graal/lir/sparc/SPARCFrameMap.java
--- a/graal/com.oracle.graal.lir.sparc/src/com/oracle/graal/lir/sparc/SPARCFrameMap.java	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.lir.sparc/src/com/oracle/graal/lir/sparc/SPARCFrameMap.java	Mon Apr 28 11:18:15 2014 +0200
@@ -24,6 +24,7 @@
 
 import com.oracle.graal.api.code.*;
 import com.oracle.graal.api.meta.*;
+import com.oracle.graal.asm.*;
 import com.oracle.graal.lir.*;
 
 /**
@@ -33,7 +34,7 @@
  *
  * 
  *   Base       Contents
- *
+ * 
  *            :                                :  -----
  *   caller   | incoming overflow argument n   |    ^
  *   frame    :     ...                        :    | positive
@@ -88,8 +89,7 @@
 
     @Override
     protected int alignFrameSize(int size) {
-        int x = size + (target.stackAlignment - 1);
-        return (x / target.stackAlignment) * target.stackAlignment;
+        return NumUtil.roundUp(size, target.stackAlignment);
     }
 
     @Override
diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.lir.sparc/src/com/oracle/graal/lir/sparc/SPARCMathIntrinsicOp.java
--- a/graal/com.oracle.graal.lir.sparc/src/com/oracle/graal/lir/sparc/SPARCMathIntrinsicOp.java	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.lir.sparc/src/com/oracle/graal/lir/sparc/SPARCMathIntrinsicOp.java	Mon Apr 28 11:18:15 2014 +0200
@@ -27,7 +27,7 @@
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.asm.sparc.SPARCAssembler.Fsqrtd;
 import com.oracle.graal.asm.sparc.*;
-import com.oracle.graal.graph.*;
+import com.oracle.graal.compiler.common.*;
 import com.oracle.graal.lir.*;
 import com.oracle.graal.lir.asm.*;
 
diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.lir.sparc/src/com/oracle/graal/lir/sparc/SPARCMove.java
--- a/graal/com.oracle.graal.lir.sparc/src/com/oracle/graal/lir/sparc/SPARCMove.java	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.lir.sparc/src/com/oracle/graal/lir/sparc/SPARCMove.java	Mon Apr 28 11:18:15 2014 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 2014, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -23,33 +23,15 @@
 package com.oracle.graal.lir.sparc;
 
 import static com.oracle.graal.api.code.ValueUtil.*;
+import static com.oracle.graal.asm.sparc.SPARCMacroAssembler.*;
 import static com.oracle.graal.lir.LIRInstruction.OperandFlag.*;
 import static com.oracle.graal.sparc.SPARC.*;
 
 import com.oracle.graal.api.code.*;
+import com.oracle.graal.api.code.CompilationResult.*;
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.asm.sparc.*;
-import com.oracle.graal.asm.sparc.SPARCAssembler.Add;
-import com.oracle.graal.asm.sparc.SPARCAssembler.Lddf;
-import com.oracle.graal.asm.sparc.SPARCAssembler.Ldf;
-import com.oracle.graal.asm.sparc.SPARCAssembler.Ldsb;
-import com.oracle.graal.asm.sparc.SPARCAssembler.Ldsh;
-import com.oracle.graal.asm.sparc.SPARCAssembler.Ldsw;
-import com.oracle.graal.asm.sparc.SPARCAssembler.Lduh;
-import com.oracle.graal.asm.sparc.SPARCAssembler.Ldx;
-import com.oracle.graal.asm.sparc.SPARCAssembler.Membar;
-import com.oracle.graal.asm.sparc.SPARCAssembler.Rdpc;
-import com.oracle.graal.asm.sparc.SPARCAssembler.Stb;
-import com.oracle.graal.asm.sparc.SPARCAssembler.Sth;
-import com.oracle.graal.asm.sparc.SPARCAssembler.Stw;
-import com.oracle.graal.asm.sparc.SPARCAssembler.Stx;
-import com.oracle.graal.asm.sparc.SPARCMacroAssembler.Cas;
-import com.oracle.graal.asm.sparc.SPARCMacroAssembler.Casx;
-import com.oracle.graal.asm.sparc.SPARCMacroAssembler.Clr;
-import com.oracle.graal.asm.sparc.SPARCMacroAssembler.Mov;
-import com.oracle.graal.asm.sparc.SPARCMacroAssembler.Setuw;
-import com.oracle.graal.asm.sparc.SPARCMacroAssembler.Setx;
-import com.oracle.graal.graph.*;
+import com.oracle.graal.compiler.common.*;
 import com.oracle.graal.lir.*;
 import com.oracle.graal.lir.StandardOp.ImplicitNullCheck;
 import com.oracle.graal.lir.StandardOp.MoveOp;
@@ -154,32 +136,33 @@
 
         @Override
         public void emitMemAccess(SPARCMacroAssembler masm) {
-            SPARCAddress addr = address.toAddress();
+            final SPARCAddress addr = address.toAddress();
+            final Register dst = asRegister(result);
             switch (kind) {
                 case Boolean:
                 case Byte:
-                    new Ldsb(addr, asRegister(result)).emit(masm);
+                    new Ldsb(addr, dst).emit(masm);
                     break;
                 case Short:
-                    new Ldsh(addr, asRegister(result)).emit(masm);
+                    new Ldsh(addr, dst).emit(masm);
                     break;
                 case Char:
-                    new Lduh(addr, asRegister(result)).emit(masm);
+                    new Lduh(addr, dst).emit(masm);
                     break;
                 case Int:
-                    new Ldsw(addr, asRegister(result)).emit(masm);
+                    new Ldsw(addr, dst).emit(masm);
                     break;
                 case Long:
-                    new Ldx(addr, asRegister(result)).emit(masm);
+                    new Ldx(addr, dst).emit(masm);
                     break;
                 case Float:
-                    new Ldf(addr, asRegister(result)).emit(masm);
+                    new Ldf(addr, dst).emit(masm);
                     break;
                 case Double:
-                    new Lddf(addr, asRegister(result)).emit(masm);
+                    new Lddf(addr, dst).emit(masm);
                     break;
                 case Object:
-                    new Ldx(addr, asRegister(result)).emit(masm);
+                    new Ldx(addr, dst).emit(masm);
                     break;
                 default:
                     throw GraalInternalError.shouldNotReachHere();
@@ -208,6 +191,26 @@
         }
     }
 
+    public static class LoadDataAddressOp extends SPARCLIRInstruction {
+
+        @Def({REG}) protected AllocatableValue result;
+        private final byte[] data;
+
+        public LoadDataAddressOp(AllocatableValue result, byte[] data) {
+            this.result = result;
+            this.data = data;
+        }
+
+        @Override
+        public void emitCode(CompilationResultBuilder crb, SPARCMacroAssembler masm) {
+            RawData rawData = new RawData(data, 16);
+            SPARCAddress addr = (SPARCAddress) crb.recordDataReferenceInCode(rawData);
+            assert addr == masm.getPlaceholder();
+            final boolean forceRelocatable = true;
+            new Setx(0, asRegister(result), forceRelocatable).emit(masm);
+        }
+    }
+
     public static class MembarOp extends SPARCLIRInstruction {
 
         private final int barriers;
@@ -395,19 +398,25 @@
     }
 
     private static void reg2reg(SPARCAssembler masm, Value result, Value input) {
-        if (asRegister(input).equals(asRegister(result))) {
+        final Register src = asRegister(input);
+        final Register dst = asRegister(result);
+        if (src.equals(dst)) {
             return;
         }
         switch (input.getKind()) {
             case Int:
             case Long:
             case Object:
-                new Mov(asRegister(input), asRegister(result)).emit(masm);
+                new Mov(src, dst).emit(masm);
                 break;
             case Float:
+                new Fmovs(src, dst).emit(masm);
+                break;
             case Double:
+                new Fmovd(src, dst).emit(masm);
+                break;
             default:
-                throw GraalInternalError.shouldNotReachHere("missing: " + input.getKind());
+                throw GraalInternalError.shouldNotReachHere();
         }
     }
 
@@ -423,7 +432,11 @@
                 new Stx(src, dst).emit(masm);
                 break;
             case Float:
+                new Stf(src, dst).emit(masm);
+                break;
             case Double:
+                new Stdf(src, dst).emit(masm);
+                break;
             default:
                 throw GraalInternalError.shouldNotReachHere();
         }
@@ -461,7 +474,7 @@
                     }
                 }
                 break;
-            case Long: {
+            case Long:
                 if (crb.codeCache.needsDataPatch(input)) {
                     crb.recordInlineDataInCode(input);
                     new Setx(input.asLong(), asRegister(result), true).emit(masm);
@@ -473,8 +486,10 @@
                     }
                 }
                 break;
-            }
-            case Object: {
+            case Float:
+                new Ldf((SPARCAddress) crb.asFloatConstRef(input), asFloatReg(result)).emit(masm);
+                break;
+            case Object:
                 if (input.isNull()) {
                     new Clr(asRegister(result)).emit(masm);
                 } else if (crb.target.inlineObjects) {
@@ -488,7 +503,6 @@
                     throw GraalInternalError.shouldNotReachHere("the patched offset might be too big for the load");
                 }
                 break;
-            }
             default:
                 throw GraalInternalError.shouldNotReachHere("missing: " + input.getKind());
         }
diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.lir.sparc/src/com/oracle/graal/lir/sparc/SPARCSaveRegistersOp.java
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.lir.sparc/src/com/oracle/graal/lir/sparc/SPARCSaveRegistersOp.java	Mon Apr 28 11:18:15 2014 +0200
@@ -0,0 +1,133 @@
+/*
+ * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.graal.lir.sparc;
+
+import static com.oracle.graal.lir.LIRInstruction.OperandFlag.*;
+
+import java.util.*;
+
+import com.oracle.graal.api.code.*;
+import com.oracle.graal.asm.sparc.*;
+import com.oracle.graal.lir.*;
+import com.oracle.graal.lir.StandardOp.SaveRegistersOp;
+import com.oracle.graal.lir.asm.*;
+
+/**
+ * Saves registers to stack slots.
+ */
+@Opcode("SAVE_REGISTER")
+public class SPARCSaveRegistersOp extends SPARCLIRInstruction implements SaveRegistersOp {
+
+    /**
+     * The registers (potentially) saved by this operation.
+     */
+    protected final Register[] savedRegisters;
+
+    /**
+     * The slots to which the registers are saved.
+     */
+    @Def(STACK) protected final StackSlot[] slots;
+
+    /**
+     * Specifies if {@link #remove(Set)} should have an effect.
+     */
+    protected final boolean supportsRemove;
+
+    /**
+     *
+     * @param savedRegisters the registers saved by this operation which may be subject to
+     *            {@linkplain #remove(Set) pruning}
+     * @param slots the slots to which the registers are saved
+     * @param supportsRemove determines if registers can be {@linkplain #remove(Set) pruned}
+     */
+    public SPARCSaveRegistersOp(Register[] savedRegisters, StackSlot[] slots, boolean supportsRemove) {
+        this.savedRegisters = savedRegisters;
+        this.slots = slots;
+        this.supportsRemove = supportsRemove;
+    }
+
+    private static void saveRegister(CompilationResultBuilder crb, SPARCMacroAssembler masm, StackSlot result, Register register) {
+        RegisterValue input = register.asValue(result.getKind());
+        SPARCMove.move(crb, masm, result, input);
+    }
+
+    @Override
+    public void emitCode(CompilationResultBuilder crb, SPARCMacroAssembler masm) {
+        for (int i = 0; i < savedRegisters.length; i++) {
+            if (savedRegisters[i] != null) {
+                saveRegister(crb, masm, slots[i], savedRegisters[i]);
+            }
+        }
+    }
+
+    public StackSlot[] getSlots() {
+        return slots;
+    }
+
+    public boolean supportsRemove() {
+        return supportsRemove;
+    }
+
+    public int remove(Set doNotSave) {
+        if (!supportsRemove) {
+            throw new UnsupportedOperationException();
+        }
+        return prune(doNotSave, savedRegisters);
+    }
+
+    static int prune(Set toRemove, Register[] registers) {
+        int pruned = 0;
+        for (int i = 0; i < registers.length; i++) {
+            if (registers[i] != null) {
+                if (toRemove.contains(registers[i])) {
+                    registers[i] = null;
+                    pruned++;
+                }
+            }
+        }
+        return pruned;
+    }
+
+    public RegisterSaveLayout getMap(FrameMap frameMap) {
+        int total = 0;
+        for (int i = 0; i < savedRegisters.length; i++) {
+            if (savedRegisters[i] != null) {
+                total++;
+            }
+        }
+        Register[] keys = new Register[total];
+        int[] values = new int[total];
+        if (total != 0) {
+            int mapIndex = 0;
+            for (int i = 0; i < savedRegisters.length; i++) {
+                if (savedRegisters[i] != null) {
+                    keys[mapIndex] = savedRegisters[i];
+                    values[mapIndex] = frameMap.indexForStackSlot(slots[i]);
+                    mapIndex++;
+                }
+            }
+            assert mapIndex == total;
+        }
+        return new RegisterSaveLayout(keys, values);
+    }
+}
diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.lir.sparc/src/com/oracle/graal/lir/sparc/SPARCTestOp.java
--- a/graal/com.oracle.graal.lir.sparc/src/com/oracle/graal/lir/sparc/SPARCTestOp.java	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.lir.sparc/src/com/oracle/graal/lir/sparc/SPARCTestOp.java	Mon Apr 28 11:18:15 2014 +0200
@@ -30,7 +30,7 @@
 import com.oracle.graal.asm.sparc.SPARCAssembler.Ldsw;
 import com.oracle.graal.asm.sparc.SPARCAssembler.Ldx;
 import com.oracle.graal.asm.sparc.SPARCMacroAssembler.Cmp;
-import com.oracle.graal.graph.*;
+import com.oracle.graal.compiler.common.*;
 import com.oracle.graal.lir.asm.*;
 
 public class SPARCTestOp extends SPARCLIRInstruction {
diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.lir/src/com/oracle/graal/lir/CompositeValueClass.java
--- a/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/CompositeValueClass.java	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/CompositeValueClass.java	Mon Apr 28 11:18:15 2014 +0200
@@ -25,7 +25,7 @@
 import java.lang.reflect.*;
 import java.util.*;
 
-import com.oracle.graal.graph.*;
+import com.oracle.graal.compiler.common.*;
 import com.oracle.graal.lir.CompositeValue.Component;
 import com.oracle.graal.lir.LIRInstruction.OperandFlag;
 import com.oracle.graal.lir.LIRInstruction.OperandMode;
@@ -86,7 +86,7 @@
     @Override
     protected void rescanFieldOffsets(CalcOffset calc) {
         ValueFieldScanner scanner = new ValueFieldScanner(calc);
-        scanner.scan(clazz);
+        scanner.scan(getClazz());
 
         OperandModeAnnotation mode = scanner.valueAnnotations.get(CompositeValue.Component.class);
         copyInto(componentOffsets, sortedLongCopy(mode.scalarOffsets, mode.arrayOffsets));
@@ -108,7 +108,7 @@
         }
 
         @Override
-        protected void scan(Class clazz) {
+        public void scan(Class clazz) {
             super.scan(clazz);
         }
 
@@ -127,7 +127,7 @@
     @Override
     public String toString() {
         StringBuilder str = new StringBuilder();
-        str.append(getClass().getSimpleName()).append(" ").append(clazz.getSimpleName()).append(" component[");
+        str.append(getClass().getSimpleName()).append(" ").append(getClazz().getSimpleName()).append(" component[");
         for (int i = 0; i < componentOffsets.length; i++) {
             str.append(i == 0 ? "" : ", ").append(componentOffsets[i]);
         }
diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.lir/src/com/oracle/graal/lir/ControlFlowOptimizer.java
--- a/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/ControlFlowOptimizer.java	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/ControlFlowOptimizer.java	Mon Apr 28 11:18:15 2014 +0200
@@ -27,7 +27,7 @@
 import java.util.*;
 
 import com.oracle.graal.debug.*;
-import com.oracle.graal.nodes.cfg.*;
+import com.oracle.graal.compiler.common.cfg.*;
 
 /**
  * This class performs basic optimizations on the control flow graph after LIR generation.
@@ -49,7 +49,7 @@
     /**
      * Checks whether a block can be deleted. Only blocks with exactly one successor and an
      * unconditional branch to this successor are eligable.
-     * 
+     *
      * @param block the block checked for deletion
      * @return whether the block can be deleted
      */
diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.lir/src/com/oracle/graal/lir/EdgeMoveOptimizer.java
--- a/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/EdgeMoveOptimizer.java	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/EdgeMoveOptimizer.java	Mon Apr 28 11:18:15 2014 +0200
@@ -24,8 +24,8 @@
 
 import java.util.*;
 
+import com.oracle.graal.compiler.common.cfg.*;
 import com.oracle.graal.lir.StandardOp.MoveOp;
-import com.oracle.graal.nodes.cfg.*;
 
 /**
  * This class optimizes moves, particularly those that result from eliminating SSA form.
diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.lir/src/com/oracle/graal/lir/LIR.java
--- a/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/LIR.java	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/LIR.java	Mon Apr 28 11:18:15 2014 +0200
@@ -25,9 +25,9 @@
 import java.util.*;
 
 import com.oracle.graal.api.meta.*;
+import com.oracle.graal.compiler.common.cfg.*;
 import com.oracle.graal.lir.LIRInstruction.StateProcedure;
 import com.oracle.graal.lir.StandardOp.BlockEndOp;
-import com.oracle.graal.nodes.cfg.*;
 
 /**
  * This class implements the overall container for the LIR graph and directs its construction,
@@ -105,7 +105,7 @@
 
     /**
      * Gets the linear scan ordering of blocks as a list.
-     * 
+     *
      * @return the blocks in linear scan order
      */
     public List> linearScanOrder() {
diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.lir/src/com/oracle/graal/lir/LIRInstruction.java
--- a/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/LIRInstruction.java	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/LIRInstruction.java	Mon Apr 28 11:18:15 2014 +0200
@@ -30,8 +30,8 @@
 
 import com.oracle.graal.api.code.*;
 import com.oracle.graal.api.meta.*;
+import com.oracle.graal.compiler.common.*;
 import com.oracle.graal.debug.*;
-import com.oracle.graal.graph.*;
 import com.oracle.graal.lir.asm.*;
 
 /**
diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.lir/src/com/oracle/graal/lir/LIRInstructionClass.java
--- a/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/LIRInstructionClass.java	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/LIRInstructionClass.java	Mon Apr 28 11:18:15 2014 +0200
@@ -27,7 +27,7 @@
 
 import com.oracle.graal.api.code.*;
 import com.oracle.graal.api.meta.*;
-import com.oracle.graal.graph.*;
+import com.oracle.graal.compiler.common.*;
 import com.oracle.graal.lir.LIRInstruction.OperandFlag;
 import com.oracle.graal.lir.LIRInstruction.OperandMode;
 import com.oracle.graal.lir.LIRInstruction.StateProcedure;
@@ -118,7 +118,7 @@
     @Override
     protected void rescanFieldOffsets(CalcOffset calc) {
         InstructionFieldScanner scanner = new InstructionFieldScanner(calc);
-        scanner.scan(clazz);
+        scanner.scan(getClazz());
 
         OperandModeAnnotation mode = scanner.valueAnnotations.get(LIRInstruction.Use.class);
         copyInto(useOffsets, sortedLongCopy(mode.scalarOffsets, mode.arrayOffsets));
@@ -177,7 +177,7 @@
         }
 
         @Override
-        protected void scan(Class clazz) {
+        public void scan(Class clazz) {
             if (clazz.getAnnotation(Opcode.class) != null) {
                 opcodeConstant = clazz.getAnnotation(Opcode.class).value();
             }
@@ -213,7 +213,7 @@
     @Override
     public String toString() {
         StringBuilder str = new StringBuilder();
-        str.append(getClass().getSimpleName()).append(" ").append(clazz.getSimpleName()).append(" use[");
+        str.append(getClass().getSimpleName()).append(" ").append(getClazz().getSimpleName()).append(" use[");
         for (int i = 0; i < useOffsets.length; i++) {
             str.append(i == 0 ? "" : ", ").append(useOffsets[i]);
         }
diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.lir/src/com/oracle/graal/lir/LIRIntrospection.java
--- a/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/LIRIntrospection.java	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/LIRIntrospection.java	Mon Apr 28 11:18:15 2014 +0200
@@ -31,7 +31,7 @@
 
 import com.oracle.graal.api.code.*;
 import com.oracle.graal.api.meta.*;
-import com.oracle.graal.graph.*;
+import com.oracle.graal.compiler.common.*;
 import com.oracle.graal.lir.LIRInstruction.OperandFlag;
 import com.oracle.graal.lir.LIRInstruction.OperandMode;
 import com.oracle.graal.lir.LIRInstruction.ValueProcedure;
diff -r 3dde8d8c95b8 -r 40d0022115ee 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	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/LIRVerifier.java	Mon Apr 28 11:18:15 2014 +0200
@@ -29,12 +29,12 @@
 
 import com.oracle.graal.api.code.*;
 import com.oracle.graal.api.meta.*;
+import com.oracle.graal.compiler.common.*;
+import com.oracle.graal.compiler.common.cfg.*;
 import com.oracle.graal.debug.*;
-import com.oracle.graal.graph.*;
 import com.oracle.graal.lir.LIRInstruction.OperandFlag;
 import com.oracle.graal.lir.LIRInstruction.OperandMode;
 import com.oracle.graal.lir.LIRInstruction.ValueProcedure;
-import com.oracle.graal.nodes.cfg.*;
 
 public final class LIRVerifier {
 
diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.lir/src/com/oracle/graal/lir/LabelRef.java
--- a/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/LabelRef.java	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/LabelRef.java	Mon Apr 28 11:18:15 2014 +0200
@@ -23,14 +23,14 @@
 package com.oracle.graal.lir;
 
 import com.oracle.graal.asm.*;
+import com.oracle.graal.compiler.common.cfg.*;
 import com.oracle.graal.lir.StandardOp.BranchOp;
 import com.oracle.graal.lir.StandardOp.JumpOp;
-import com.oracle.graal.nodes.cfg.*;
 
 /**
  * LIR instructions such as {@link JumpOp} and {@link BranchOp} need to reference their target
- * {@link Block}. However, direct references are not possible since the control flow graph (and
- * therefore successors lists) can be changed by optimizations - and fixing the instructions is
+ * {@link AbstractBlock}. However, direct references are not possible since the control flow graph
+ * (and therefore successors lists) can be changed by optimizations - and fixing the instructions is
  * error prone. Therefore, we represent an edge to block B from block A via the tuple {@code (A,
  * successor-index-of-B)}. That is, indirectly by storing the index into the successor list of A.
  * Note therefore that the successor list cannot be re-ordered.
diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.lir/src/com/oracle/graal/lir/NullCheckOptimizer.java
--- a/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/NullCheckOptimizer.java	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/NullCheckOptimizer.java	Mon Apr 28 11:18:15 2014 +0200
@@ -24,9 +24,9 @@
 
 import java.util.*;
 
+import com.oracle.graal.compiler.common.cfg.*;
 import com.oracle.graal.lir.StandardOp.ImplicitNullCheck;
 import com.oracle.graal.lir.StandardOp.NullCheck;
-import com.oracle.graal.nodes.cfg.*;
 
 public final class NullCheckOptimizer {
 
diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.lir/src/com/oracle/graal/lir/RedundantMoveElimination.java
--- a/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/RedundantMoveElimination.java	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/RedundantMoveElimination.java	Mon Apr 28 11:18:15 2014 +0200
@@ -28,12 +28,12 @@
 
 import com.oracle.graal.api.code.*;
 import com.oracle.graal.api.meta.*;
+import com.oracle.graal.compiler.common.cfg.*;
 import com.oracle.graal.debug.*;
 import com.oracle.graal.lir.LIRInstruction.OperandFlag;
 import com.oracle.graal.lir.LIRInstruction.OperandMode;
 import com.oracle.graal.lir.LIRInstruction.ValueProcedure;
 import com.oracle.graal.lir.StandardOp.MoveOp;
-import com.oracle.graal.nodes.cfg.*;
 
 /**
  * Removes move instructions, where the destination value is already in place.
diff -r 3dde8d8c95b8 -r 40d0022115ee 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	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/StandardOp.java	Mon Apr 28 11:18:15 2014 +0200
@@ -29,9 +29,9 @@
 import com.oracle.graal.api.code.*;
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.asm.*;
-import com.oracle.graal.graph.*;
+import com.oracle.graal.compiler.common.*;
+import com.oracle.graal.compiler.common.cfg.*;
 import com.oracle.graal.lir.asm.*;
-import com.oracle.graal.nodes.cfg.*;
 
 /**
  * A collection of machine-independent LIR operations, as well as interfaces to be implemented for
@@ -154,7 +154,7 @@
 
         /**
          * Prunes {@code doNotSave} from the registers saved by this operation.
-         * 
+         *
          * @param doNotSave registers that should not be saved by this operation
          * @return the number of registers pruned
          * @throws UnsupportedOperationException if removal is not {@linkplain #supportsRemove()
@@ -165,7 +165,7 @@
         /**
          * Gets a map from the saved registers saved by this operation to the frame slots in which
          * they are saved.
-         * 
+         *
          * @param frameMap used to {@linkplain FrameMap#indexForStackSlot(StackSlot) convert} a
          *            virtual slot to a frame slot index
          */
diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.lir/src/com/oracle/graal/lir/SwitchStrategy.java
--- a/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/SwitchStrategy.java	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/SwitchStrategy.java	Mon Apr 28 11:18:15 2014 +0200
@@ -26,8 +26,8 @@
 
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.asm.*;
+import com.oracle.graal.compiler.common.calc.*;
 import com.oracle.graal.lir.asm.*;
-import com.oracle.graal.nodes.calc.*;
 
 /**
  * This class encapsulates different strategies on how to generate code for switch instructions.
diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.lir/src/com/oracle/graal/lir/asm/CompilationResultBuilder.java
--- a/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/asm/CompilationResultBuilder.java	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/asm/CompilationResultBuilder.java	Mon Apr 28 11:18:15 2014 +0200
@@ -30,10 +30,10 @@
 import com.oracle.graal.api.code.CompilationResult.Data;
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.asm.*;
+import com.oracle.graal.compiler.common.*;
+import com.oracle.graal.compiler.common.cfg.*;
 import com.oracle.graal.debug.*;
-import com.oracle.graal.graph.*;
 import com.oracle.graal.lir.*;
-import com.oracle.graal.nodes.cfg.*;
 
 /**
  * Fills in a {@link CompilationResult} as its code is being assembled.
@@ -88,18 +88,12 @@
         assert frameContext != null;
     }
 
-    public void setFrameSize(int frameSize) {
-        compilationResult.setFrameSize(frameSize);
+    public void setTotalFrameSize(int frameSize) {
+        compilationResult.setTotalFrameSize(frameSize);
     }
 
-    private static final CompilationResult.Mark[] NO_REFS = {};
-
     public CompilationResult.Mark recordMark(Object id) {
-        return compilationResult.recordMark(asm.position(), id, NO_REFS);
-    }
-
-    public CompilationResult.Mark recordMark(Object id, CompilationResult.Mark... references) {
-        return compilationResult.recordMark(asm.position(), id, references);
+        return compilationResult.recordMark(asm.position(), id);
     }
 
     public void blockComment(String s) {
diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.lir/src/com/oracle/graal/lir/gen/ArithmeticLIRGenerator.java
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/gen/ArithmeticLIRGenerator.java	Mon Apr 28 11:18:15 2014 +0200
@@ -0,0 +1,88 @@
+/*
+ * 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.lir.gen;
+
+import com.oracle.graal.api.meta.*;
+import com.oracle.graal.compiler.common.calc.*;
+import com.oracle.graal.compiler.common.type.*;
+import com.oracle.graal.lir.*;
+
+/**
+ * This interface can be used to generate LIR for arithmetic operations.
+ */
+public interface ArithmeticLIRGenerator {
+
+    PlatformKind getPlatformKind(Stamp stamp);
+
+    Value emitNegate(Value input);
+
+    Value emitAdd(Value a, Value b);
+
+    Value emitSub(Value a, Value b);
+
+    Value emitMul(Value a, Value b);
+
+    Value emitDiv(Value a, Value b, LIRFrameState state);
+
+    Value emitRem(Value a, Value b, LIRFrameState state);
+
+    Value emitUDiv(Value a, Value b, LIRFrameState state);
+
+    Value emitURem(Value a, Value b, LIRFrameState state);
+
+    Value emitNot(Value input);
+
+    Value emitAnd(Value a, Value b);
+
+    Value emitOr(Value a, Value b);
+
+    Value emitXor(Value a, Value b);
+
+    Value emitShl(Value a, Value b);
+
+    Value emitShr(Value a, Value b);
+
+    Value emitUShr(Value a, Value b);
+
+    Value emitFloatConvert(FloatConvert op, Value inputVal);
+
+    Value emitReinterpret(PlatformKind to, Value inputVal);
+
+    Value emitNarrow(Value inputVal, int bits);
+
+    Value emitSignExtend(Value inputVal, int fromBits, int toBits);
+
+    Value emitZeroExtend(Value inputVal, int fromBits, int toBits);
+
+    Value emitMathAbs(Value input);
+
+    Value emitMathSqrt(Value input);
+
+    Value emitMathLog(Value input, boolean base10);
+
+    Value emitMathCos(Value input);
+
+    Value emitMathSin(Value input);
+
+    Value emitMathTan(Value input);
+}
diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.lir/src/com/oracle/graal/lir/gen/LIRGenerationResult.java
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/gen/LIRGenerationResult.java	Mon Apr 28 11:18:15 2014 +0200
@@ -0,0 +1,35 @@
+/*
+ * Copyright (c) 2014, 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.graal.lir.gen;
+
+import com.oracle.graal.lir.*;
+
+public interface LIRGenerationResult {
+    FrameMap getFrameMap();
+
+    LIR getLIR();
+
+    boolean hasForeignCall();
+
+    void setForeignCall(boolean b);
+}
diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.lir/src/com/oracle/graal/lir/gen/LIRGenerationResultBase.java
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/gen/LIRGenerationResultBase.java	Mon Apr 28 11:18:15 2014 +0200
@@ -0,0 +1,59 @@
+/*
+ * Copyright (c) 2014, 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.graal.lir.gen;
+
+import com.oracle.graal.lir.*;
+
+public class LIRGenerationResultBase implements LIRGenerationResult {
+    private final LIR lir;
+    private final FrameMap frameMap;
+    /**
+     * Records whether the code being generated makes at least one foreign call.
+     */
+    private boolean hasForeignCall;
+
+    public LIRGenerationResultBase(LIR lir, FrameMap frameMap) {
+        this.lir = lir;
+        this.frameMap = frameMap;
+    }
+
+    public LIR getLIR() {
+        return lir;
+    }
+
+    /**
+     * Determines whether the code being generated makes at least one foreign call.
+     */
+    public boolean hasForeignCall() {
+        return hasForeignCall;
+    }
+
+    public final void setForeignCall(boolean hasForeignCall) {
+        this.hasForeignCall = hasForeignCall;
+    }
+
+    public final FrameMap getFrameMap() {
+        return frameMap;
+    }
+
+}
diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.lir/src/com/oracle/graal/lir/gen/LIRGenerator.java
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/gen/LIRGenerator.java	Mon Apr 28 11:18:15 2014 +0200
@@ -0,0 +1,594 @@
+/*
+ * Copyright (c) 2009, 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.lir.gen;
+
+import static com.oracle.graal.api.code.ValueUtil.*;
+import static com.oracle.graal.api.meta.Value.*;
+import static com.oracle.graal.compiler.common.GraalOptions.*;
+import static com.oracle.graal.lir.LIR.*;
+import static com.oracle.graal.lir.LIRValueUtil.*;
+
+import java.util.*;
+
+import com.oracle.graal.api.code.*;
+import com.oracle.graal.api.meta.*;
+import com.oracle.graal.asm.*;
+import com.oracle.graal.compiler.common.*;
+import com.oracle.graal.compiler.common.calc.*;
+import com.oracle.graal.compiler.common.cfg.*;
+import com.oracle.graal.compiler.common.spi.*;
+import com.oracle.graal.compiler.common.type.*;
+import com.oracle.graal.debug.*;
+import com.oracle.graal.lir.*;
+import com.oracle.graal.lir.StandardOp.BlockEndOp;
+import com.oracle.graal.lir.StandardOp.LabelOp;
+import com.oracle.graal.lir.StandardOp.NoOp;
+import com.oracle.graal.options.*;
+
+/**
+ * This class traverses the HIR instructions and generates LIR instructions from them.
+ */
+public abstract class LIRGenerator implements LIRGeneratorTool, PlatformKindTool {
+
+    public static class Options {
+        // @formatter:off
+        @Option(help = "Print HIR along side LIR as the latter is generated")
+        public static final OptionValue PrintIRWithLIR = new OptionValue<>(false);
+        @Option(help = "The trace level for the LIR generator")
+        public static final OptionValue TraceLIRGeneratorLevel = new OptionValue<>(0);
+        // @formatter:on
+    }
+
+    private final CodeGenProviders providers;
+    private final CallingConvention cc;
+
+    private AbstractBlock currentBlock;
+
+    /**
+     * Handle for an operation that loads a constant into a variable. The operation starts in the
+     * first block where the constant is used but will eventually be
+     * {@linkplain LIRGenerator#insertConstantLoads() moved} to a block dominating all usages of the
+     * constant.
+     */
+    public static class LoadConstant implements Comparable {
+        /**
+         * The index of {@link #op} within {@link #block}'s instruction list or -1 if {@code op} is
+         * to be moved to a dominator block.
+         */
+        int index;
+
+        /**
+         * The operation that loads the constant.
+         */
+        private final LIRInstruction op;
+
+        /**
+         * The block that does or will contain {@link #op}. This is initially the block where the
+         * first usage of the constant is seen during LIR generation.
+         */
+        AbstractBlock block;
+
+        /**
+         * The variable into which the constant is loaded.
+         */
+        final Variable variable;
+
+        public LoadConstant(Variable variable, AbstractBlock block, int index, LIRInstruction op) {
+            this.variable = variable;
+            this.block = block;
+            this.index = index;
+            this.op = op;
+        }
+
+        /**
+         * Sorts {@link LoadConstant} objects according to their enclosing blocks. This is used to
+         * group loads per block in {@link LIRGenerator#insertConstantLoads()}.
+         */
+        public int compareTo(LoadConstant o) {
+            if (block.getId() < o.block.getId()) {
+                return -1;
+            }
+            if (block.getId() > o.block.getId()) {
+                return 1;
+            }
+            return 0;
+        }
+
+        @Override
+        public String toString() {
+            return block + "#" + op;
+        }
+
+        /**
+         * Removes the {@link #op} from its original location if it is still at that location.
+         */
+        public void unpin(LIR lir) {
+            if (index >= 0) {
+                // Replace the move with a filler op so that the operation
+                // list does not need to be adjusted.
+                List instructions = lir.getLIRforBlock(block);
+                instructions.set(index, new NoOp(null, -1));
+                index = -1;
+            }
+        }
+
+        public AbstractBlock getBlock() {
+            return block;
+        }
+
+        public void setBlock(AbstractBlock block) {
+            this.block = block;
+        }
+
+        public Variable getVariable() {
+            return variable;
+        }
+
+        public int getIndex() {
+            return index;
+        }
+
+        public void setIndex(int index) {
+            this.index = index;
+        }
+    }
+
+    private Map constantLoads;
+
+    private LIRGenerationResult res;
+
+    /**
+     * Checks whether the supplied constant can be used without loading it into a register for store
+     * operations, i.e., on the right hand side of a memory access.
+     *
+     * @param c The constant to check.
+     * @return True if the constant can be used directly, false if the constant needs to be in a
+     *         register.
+     */
+    public abstract boolean canStoreConstant(Constant c, boolean isCompressed);
+
+    public LIRGenerator(CodeGenProviders providers, CallingConvention cc, LIRGenerationResult res) {
+        this.res = res;
+        this.providers = providers;
+        this.cc = cc;
+    }
+
+    /**
+     * Returns true if the redundant move elimination optimization should be done after register
+     * allocation.
+     */
+    public boolean canEliminateRedundantMoves() {
+        return true;
+    }
+
+    @Override
+    public TargetDescription target() {
+        return getCodeCache().getTarget();
+    }
+
+    public CodeGenProviders getProviders() {
+        return providers;
+    }
+
+    @Override
+    public MetaAccessProvider getMetaAccess() {
+        return providers.getMetaAccess();
+    }
+
+    @Override
+    public CodeCacheProvider getCodeCache() {
+        return providers.getCodeCache();
+    }
+
+    @Override
+    public ForeignCallsProvider getForeignCalls() {
+        return providers.getForeignCalls();
+    }
+
+    /**
+     * Creates a new {@linkplain Variable variable}.
+     *
+     * @param platformKind The kind of the new variable.
+     * @return a new variable
+     */
+    @Override
+    public Variable newVariable(PlatformKind platformKind) {
+        return new Variable(platformKind, res.getLIR().nextVariable());
+    }
+
+    @Override
+    public RegisterAttributes attributes(Register register) {
+        return res.getFrameMap().registerConfig.getAttributesMap()[register.number];
+    }
+
+    @Override
+    public abstract Variable emitMove(Value input);
+
+    public AllocatableValue asAllocatable(Value value) {
+        if (isAllocatableValue(value)) {
+            return asAllocatableValue(value);
+        } else {
+            return emitMove(value);
+        }
+    }
+
+    public Variable load(Value value) {
+        if (!isVariable(value)) {
+            return emitMove(value);
+        }
+        return (Variable) value;
+    }
+
+    public Value loadNonConst(Value value) {
+        if (isConstant(value) && !canInlineConstant((Constant) value)) {
+            return emitMove(value);
+        }
+        return value;
+    }
+
+    /**
+     * Determines if only oop maps are required for the code generated from the LIR.
+     */
+    public boolean needOnlyOopMaps() {
+        return false;
+    }
+
+    /**
+     * Gets the ABI specific operand used to return a value of a given kind from a method.
+     *
+     * @param kind the kind of value being returned
+     * @return the operand representing the ABI defined location used return a value of kind
+     *         {@code kind}
+     */
+    public AllocatableValue resultOperandFor(Kind kind) {
+        if (kind == Kind.Void) {
+            return ILLEGAL;
+        }
+        return res.getFrameMap().registerConfig.getReturnRegister(kind).asValue(kind);
+    }
+
+    public void append(LIRInstruction op) {
+        if (Options.PrintIRWithLIR.getValue() && !TTY.isSuppressed()) {
+            TTY.println(op.toStringWithIdPrefix());
+            TTY.println();
+        }
+        assert LIRVerifier.verify(op);
+        res.getLIR().getLIRforBlock(currentBlock).add(op);
+    }
+
+    public boolean hasBlockEnd(AbstractBlock block) {
+        List ops = getResult().getLIR().getLIRforBlock(block);
+        if (ops.size() == 0) {
+            return false;
+        }
+        return ops.get(ops.size() - 1) instanceof BlockEndOp;
+    }
+
+    public final void doBlockStart(AbstractBlock block) {
+        if (Options.PrintIRWithLIR.getValue()) {
+            TTY.print(block.toString());
+        }
+
+        currentBlock = block;
+
+        // set up the list of LIR instructions
+        assert res.getLIR().getLIRforBlock(block) == null : "LIR list already computed for this block";
+        res.getLIR().setLIRforBlock(block, new ArrayList());
+
+        append(new LabelOp(new Label(block.getId()), block.isAligned()));
+
+        if (Options.TraceLIRGeneratorLevel.getValue() >= 1) {
+            TTY.println("BEGIN Generating LIR for block B" + block.getId());
+        }
+    }
+
+    public final void doBlockEnd(AbstractBlock block) {
+
+        if (Options.TraceLIRGeneratorLevel.getValue() >= 1) {
+            TTY.println("END Generating LIR for block B" + block.getId());
+        }
+
+        currentBlock = null;
+
+        if (Options.PrintIRWithLIR.getValue()) {
+            TTY.println();
+        }
+    }
+
+    public void emitIncomingValues(Value[] params) {
+        ((LabelOp) res.getLIR().getLIRforBlock(currentBlock).get(0)).setIncomingValues(params);
+    }
+
+    public abstract void emitJump(LabelRef label);
+
+    public abstract void emitCompareBranch(PlatformKind cmpKind, Value left, Value right, Condition cond, boolean unorderedIsTrue, LabelRef trueDestination, LabelRef falseDestination,
+                    double trueDestinationProbability);
+
+    public abstract void emitOverflowCheckBranch(LabelRef overflow, LabelRef noOverflow, double overflowProbability);
+
+    public abstract void emitIntegerTestBranch(Value left, Value right, LabelRef trueDestination, LabelRef falseDestination, double trueSuccessorProbability);
+
+    public abstract Variable emitConditionalMove(PlatformKind cmpKind, Value leftVal, Value right, Condition cond, boolean unorderedIsTrue, Value trueValue, Value falseValue);
+
+    public abstract Variable emitIntegerTestMove(Value leftVal, Value right, Value trueValue, Value falseValue);
+
+    protected abstract void emitForeignCall(ForeignCallLinkage linkage, Value result, Value[] arguments, Value[] temps, LIRFrameState info);
+
+    public static AllocatableValue toStackKind(AllocatableValue value) {
+        if (value.getKind().getStackKind() != value.getKind()) {
+            // We only have stack-kinds in the LIR, so convert the operand kind for values from the
+            // calling convention.
+            if (isRegister(value)) {
+                return asRegister(value).asValue(value.getKind().getStackKind());
+            } else if (isStackSlot(value)) {
+                return StackSlot.get(value.getKind().getStackKind(), asStackSlot(value).getRawOffset(), asStackSlot(value).getRawAddFrameSize());
+            } else {
+                throw GraalInternalError.shouldNotReachHere();
+            }
+        }
+        return value;
+    }
+
+    @Override
+    public Variable emitForeignCall(ForeignCallLinkage linkage, LIRFrameState frameState, Value... args) {
+        LIRFrameState state = null;
+        if (linkage.canDeoptimize()) {
+            if (frameState != null) {
+                state = frameState;
+            } else {
+                assert needOnlyOopMaps();
+                state = new LIRFrameState(null, null, null);
+            }
+        }
+
+        // move the arguments into the correct location
+        CallingConvention linkageCc = linkage.getOutgoingCallingConvention();
+        res.getFrameMap().callsMethod(linkageCc);
+        assert linkageCc.getArgumentCount() == args.length : "argument count mismatch";
+        Value[] argLocations = new Value[args.length];
+        for (int i = 0; i < args.length; i++) {
+            Value arg = args[i];
+            AllocatableValue loc = linkageCc.getArgument(i);
+            emitMove(loc, arg);
+            argLocations[i] = loc;
+        }
+        res.setForeignCall(true);
+        emitForeignCall(linkage, linkageCc.getReturn(), argLocations, linkage.getTemporaries(), state);
+
+        if (isLegal(linkageCc.getReturn())) {
+            return emitMove(linkageCc.getReturn());
+        } else {
+            return null;
+        }
+    }
+
+    public void emitStrategySwitch(Constant[] keyConstants, double[] keyProbabilities, LabelRef[] keyTargets, LabelRef defaultTarget, Variable value) {
+        int keyCount = keyConstants.length;
+        SwitchStrategy strategy = SwitchStrategy.getBestStrategy(keyProbabilities, keyConstants, keyTargets);
+        long valueRange = keyConstants[keyCount - 1].asLong() - keyConstants[0].asLong() + 1;
+        double tableSwitchDensity = keyCount / (double) valueRange;
+        /*
+         * This heuristic tries to find a compromise between the effort for the best switch strategy
+         * and the density of a tableswitch. If the effort for the strategy is at least 4, then a
+         * tableswitch is preferred if better than a certain value that starts at 0.5 and lowers
+         * gradually with additional effort.
+         */
+        if (strategy.getAverageEffort() < 4 || tableSwitchDensity < (1 / Math.sqrt(strategy.getAverageEffort()))) {
+            emitStrategySwitch(strategy, value, keyTargets, defaultTarget);
+        } else {
+            int minValue = keyConstants[0].asInt();
+            assert valueRange < Integer.MAX_VALUE;
+            LabelRef[] targets = new LabelRef[(int) valueRange];
+            for (int i = 0; i < valueRange; i++) {
+                targets[i] = defaultTarget;
+            }
+            for (int i = 0; i < keyCount; i++) {
+                targets[keyConstants[i].asInt() - minValue] = keyTargets[i];
+            }
+            emitTableSwitch(minValue, defaultTarget, targets, value);
+        }
+    }
+
+    public abstract void emitStrategySwitch(SwitchStrategy strategy, Variable key, LabelRef[] keyTargets, LabelRef defaultTarget);
+
+    protected abstract void emitTableSwitch(int lowKey, LabelRef defaultTarget, LabelRef[] targets, Value key);
+
+    public CallingConvention getCallingConvention() {
+        return cc;
+    }
+
+    @Override
+    public void beforeRegisterAllocation() {
+        insertConstantLoads();
+    }
+
+    /**
+     * Moves deferred {@linkplain LoadConstant loads} of constants into blocks dominating all usages
+     * of the constant. Any operations inserted into a block are guaranteed to be immediately prior
+     * to the first control flow instruction near the end of the block.
+     */
+    private void insertConstantLoads() {
+        if (constantLoads != null) {
+            // Remove loads where all usages are in the same block.
+            for (Iterator> iter = constantLoads.entrySet().iterator(); iter.hasNext();) {
+                LoadConstant lc = iter.next().getValue();
+
+                // Move loads of constant outside of loops
+                if (OptScheduleOutOfLoops.getValue()) {
+                    AbstractBlock outOfLoopDominator = lc.block;
+                    while (outOfLoopDominator.getLoop() != null) {
+                        outOfLoopDominator = outOfLoopDominator.getDominator();
+                    }
+                    if (outOfLoopDominator != lc.block) {
+                        lc.unpin(res.getLIR());
+                        lc.block = outOfLoopDominator;
+                    }
+                }
+
+                if (lc.index != -1) {
+                    assert res.getLIR().getLIRforBlock(lc.block).get(lc.index) == lc.op;
+                    iter.remove();
+                }
+            }
+            if (constantLoads.isEmpty()) {
+                return;
+            }
+
+            // Sorting groups the loads per block.
+            LoadConstant[] groupedByBlock = constantLoads.values().toArray(new LoadConstant[constantLoads.size()]);
+            Arrays.sort(groupedByBlock);
+
+            int groupBegin = 0;
+            while (true) {
+                int groupEnd = groupBegin + 1;
+                AbstractBlock block = groupedByBlock[groupBegin].block;
+                while (groupEnd < groupedByBlock.length && groupedByBlock[groupEnd].block == block) {
+                    groupEnd++;
+                }
+                int groupSize = groupEnd - groupBegin;
+
+                List ops = res.getLIR().getLIRforBlock(block);
+                int lastIndex = ops.size() - 1;
+                assert ops.get(lastIndex) instanceof BlockEndOp;
+                int insertionIndex = lastIndex;
+                for (int i = Math.max(0, lastIndex - MAX_EXCEPTION_EDGE_OP_DISTANCE_FROM_END); i < lastIndex; i++) {
+                    if (getExceptionEdge(ops.get(i)) != null) {
+                        insertionIndex = i;
+                        break;
+                    }
+                }
+
+                if (groupSize == 1) {
+                    ops.add(insertionIndex, groupedByBlock[groupBegin].op);
+                } else {
+                    assert groupSize > 1;
+                    List moves = new ArrayList<>(groupSize);
+                    for (int i = groupBegin; i < groupEnd; i++) {
+                        moves.add(groupedByBlock[i].op);
+                    }
+                    ops.addAll(insertionIndex, moves);
+                }
+
+                if (groupEnd == groupedByBlock.length) {
+                    break;
+                }
+                groupBegin = groupEnd;
+            }
+            constantLoads = null;
+        }
+    }
+
+    /**
+     * Gets a garbage value for a given kind.
+     */
+    protected Constant zapValueForKind(PlatformKind kind) {
+        long dead = 0xDEADDEADDEADDEADL;
+        switch ((Kind) kind) {
+            case Boolean:
+                return Constant.FALSE;
+            case Byte:
+                return Constant.forByte((byte) dead);
+            case Char:
+                return Constant.forChar((char) dead);
+            case Short:
+                return Constant.forShort((short) dead);
+            case Int:
+                return Constant.forInt((int) dead);
+            case Double:
+                return Constant.forDouble(Double.longBitsToDouble(dead));
+            case Float:
+                return Constant.forFloat(Float.intBitsToFloat((int) dead));
+            case Long:
+                return Constant.forLong(dead);
+            case Object:
+                return Constant.NULL_OBJECT;
+            default:
+                throw new IllegalArgumentException(kind.toString());
+        }
+    }
+
+    /**
+     * Default implementation: Return the Java stack kind for each stamp.
+     */
+    public PlatformKind getPlatformKind(Stamp stamp) {
+        return stamp.getPlatformKind(this);
+    }
+
+    public PlatformKind getIntegerKind(int bits) {
+        if (bits <= 8) {
+            return Kind.Byte;
+        } else if (bits <= 16) {
+            return Kind.Short;
+        } else if (bits <= 32) {
+            return Kind.Int;
+        } else {
+            assert bits <= 64;
+            return Kind.Long;
+        }
+    }
+
+    public PlatformKind getFloatingKind(int bits) {
+        switch (bits) {
+            case 32:
+                return Kind.Float;
+            case 64:
+                return Kind.Double;
+            default:
+                throw GraalInternalError.shouldNotReachHere();
+        }
+    }
+
+    public PlatformKind getObjectKind() {
+        return Kind.Object;
+    }
+
+    public abstract void emitBitCount(Variable result, Value operand);
+
+    public abstract void emitBitScanForward(Variable result, Value operand);
+
+    public abstract void emitBitScanReverse(Variable result, Value operand);
+
+    public abstract void emitByteSwap(Variable result, Value operand);
+
+    public abstract void emitArrayEquals(Kind kind, Variable result, Value array1, Value array2, Value length);
+
+    public AbstractBlock getCurrentBlock() {
+        return currentBlock;
+    }
+
+    void setCurrentBlock(AbstractBlock block) {
+        currentBlock = block;
+    }
+
+    public LIRGenerationResult getResult() {
+        return res;
+    }
+
+    public Map getConstantLoads() {
+        return constantLoads;
+    }
+
+    public void setConstantLoads(Map constantLoads) {
+        this.constantLoads = constantLoads;
+    }
+}
diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.lir/src/com/oracle/graal/lir/gen/LIRGeneratorTool.java
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/gen/LIRGeneratorTool.java	Mon Apr 28 11:18:15 2014 +0200
@@ -0,0 +1,199 @@
+/*
+ * Copyright (c) 2011, 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.lir.gen;
+
+import java.util.*;
+
+import com.oracle.graal.api.code.*;
+import com.oracle.graal.api.meta.*;
+import com.oracle.graal.compiler.common.*;
+import com.oracle.graal.compiler.common.calc.*;
+import com.oracle.graal.compiler.common.cfg.*;
+import com.oracle.graal.compiler.common.spi.*;
+import com.oracle.graal.lir.*;
+import com.oracle.graal.lir.gen.LIRGenerator.*;
+
+public interface LIRGeneratorTool extends ArithmeticLIRGenerator {
+
+    CodeGenProviders getProviders();
+
+    TargetDescription target();
+
+    MetaAccessProvider getMetaAccess();
+
+    CodeCacheProvider getCodeCache();
+
+    ForeignCallsProvider getForeignCalls();
+
+    AbstractBlock getCurrentBlock();
+
+    LIRGenerationResult getResult();
+
+    boolean hasBlockEnd(AbstractBlock block);
+
+    void doBlockStart(AbstractBlock block);
+
+    void doBlockEnd(AbstractBlock block);
+
+    Map getConstantLoads();
+
+    void setConstantLoads(Map constantLoads);
+
+    Value emitLoad(PlatformKind kind, Value address, LIRFrameState state);
+
+    void emitStore(PlatformKind kind, Value address, Value input, LIRFrameState state);
+
+    Value emitCompareAndSwap(Value address, Value expectedValue, Value newValue, Value trueValue, Value falseValue);
+
+    /**
+     * Emit an atomic read-and-add instruction.
+     *
+     * @param address address of the value to be read and written
+     * @param delta the value to be added
+     */
+    default Value emitAtomicReadAndAdd(Value address, Value delta) {
+        throw GraalInternalError.unimplemented();
+    }
+
+    /**
+     * Emit an atomic read-and-write instruction.
+     *
+     * @param address address of the value to be read and written
+     * @param newValue the new value to be written
+     */
+    default Value emitAtomicReadAndWrite(Value address, Value newValue) {
+        throw GraalInternalError.unimplemented();
+    }
+
+    void emitDeoptimize(Value actionAndReason, Value failedSpeculation, LIRFrameState state);
+
+    Variable emitForeignCall(ForeignCallLinkage linkage, LIRFrameState state, Value... args);
+
+    /**
+     * Checks whether the supplied constant can be used without loading it into a register for most
+     * operations, i.e., for commonly used arithmetic, logical, and comparison operations.
+     *
+     * @param c The constant to check.
+     * @return True if the constant can be used directly, false if the constant needs to be in a
+     *         register.
+     */
+    boolean canInlineConstant(Constant c);
+
+    boolean canStoreConstant(Constant c, boolean isCompressed);
+
+    RegisterAttributes attributes(Register register);
+
+    Variable newVariable(PlatformKind kind);
+
+    Variable emitMove(Value input);
+
+    void emitMove(AllocatableValue dst, Value src);
+
+    /**
+     * Emits an op that loads the address of some raw data.
+     *
+     * @param dst the variable into which the address is loaded
+     * @param data the data to be installed with the generated code
+     */
+    void emitData(AllocatableValue dst, byte[] data);
+
+    Value emitAddress(Value base, long displacement, Value index, int scale);
+
+    Value emitAddress(StackSlot slot);
+
+    void emitMembar(int barriers);
+
+    void emitUnwind(Value operand);
+
+    /**
+     * Called just before register allocation is performed on the LIR owned by this generator.
+     * Overriding implementations of this method must call the overridden method.
+     */
+    void beforeRegisterAllocation();
+
+    void emitIncomingValues(Value[] params);
+
+    /**
+     * Emits a return instruction. Implementations need to insert a move if the input is not in the
+     * correct location.
+     */
+    void emitReturn(Value input);
+
+    AllocatableValue asAllocatable(Value value);
+
+    Variable load(Value value);
+
+    Value loadNonConst(Value value);
+
+    /**
+     * Returns true if the redundant move elimination optimization should be done after register
+     * allocation.
+     */
+    boolean canEliminateRedundantMoves();
+
+    /**
+     * Determines if only oop maps are required for the code generated from the LIR.
+     */
+    boolean needOnlyOopMaps();
+
+    /**
+     * Gets the ABI specific operand used to return a value of a given kind from a method.
+     *
+     * @param kind the kind of value being returned
+     * @return the operand representing the ABI defined location used return a value of kind
+     *         {@code kind}
+     */
+    AllocatableValue resultOperandFor(Kind kind);
+
+    void append(LIRInstruction op);
+
+    void emitJump(LabelRef label);
+
+    void emitCompareBranch(PlatformKind cmpKind, Value left, Value right, Condition cond, boolean unorderedIsTrue, LabelRef trueDestination, LabelRef falseDestination,
+                    double trueDestinationProbability);
+
+    void emitOverflowCheckBranch(LabelRef overflow, LabelRef noOverflow, double overflowProbability);
+
+    void emitIntegerTestBranch(Value left, Value right, LabelRef trueDestination, LabelRef falseDestination, double trueSuccessorProbability);
+
+    Variable emitConditionalMove(PlatformKind cmpKind, Value leftVal, Value right, Condition cond, boolean unorderedIsTrue, Value trueValue, Value falseValue);
+
+    Variable emitIntegerTestMove(Value leftVal, Value right, Value trueValue, Value falseValue);
+
+    void emitStrategySwitch(Constant[] keyConstants, double[] keyProbabilities, LabelRef[] keyTargets, LabelRef defaultTarget, Variable value);
+
+    void emitStrategySwitch(SwitchStrategy strategy, Variable key, LabelRef[] keyTargets, LabelRef defaultTarget);
+
+    CallingConvention getCallingConvention();
+
+    void emitBitCount(Variable result, Value operand);
+
+    void emitBitScanForward(Variable result, Value operand);
+
+    void emitBitScanReverse(Variable result, Value operand);
+
+    void emitByteSwap(Variable result, Value operand);
+
+    void emitArrayEquals(Kind kind, Variable result, Value array1, Value array2, Value length);
+
+}
diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.loop/src/com/oracle/graal/loop/BasicInductionVariable.java
--- a/graal/com.oracle.graal.loop/src/com/oracle/graal/loop/BasicInductionVariable.java	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.loop/src/com/oracle/graal/loop/BasicInductionVariable.java	Mon Apr 28 11:18:15 2014 +0200
@@ -22,10 +22,10 @@
  */
 package com.oracle.graal.loop;
 
-import com.oracle.graal.graph.*;
+import com.oracle.graal.compiler.common.*;
+import com.oracle.graal.compiler.common.type.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.calc.*;
-import com.oracle.graal.nodes.type.*;
 
 public class BasicInductionVariable extends InductionVariable {
 
diff -r 3dde8d8c95b8 -r 40d0022115ee 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	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.loop/src/com/oracle/graal/loop/CountedLoopInfo.java	Mon Apr 28 11:18:15 2014 +0200
@@ -25,11 +25,11 @@
 import static com.oracle.graal.nodes.calc.IntegerArithmeticNode.*;
 
 import com.oracle.graal.api.meta.*;
+import com.oracle.graal.compiler.common.type.*;
 import com.oracle.graal.loop.InductionVariable.Direction;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.calc.*;
 import com.oracle.graal.nodes.extended.*;
-import com.oracle.graal.nodes.type.*;
 
 public class CountedLoopInfo {
 
@@ -37,9 +37,9 @@
     private InductionVariable iv;
     private ValueNode end;
     private boolean oneOff;
-    private AbstractBeginNode body;
+    private BeginNode body;
 
-    CountedLoopInfo(LoopEx loop, InductionVariable iv, ValueNode end, boolean oneOff, AbstractBeginNode body) {
+    CountedLoopInfo(LoopEx loop, InductionVariable iv, ValueNode end, boolean oneOff, BeginNode body) {
         this.loop = loop;
         this.iv = iv;
         this.end = end;
@@ -117,7 +117,7 @@
         return oneOff;
     }
 
-    public AbstractBeginNode getBody() {
+    public BeginNode getBody() {
         return body;
     }
 
@@ -143,14 +143,14 @@
         CompareNode cond; // we use a negated guard with a < condition to achieve a >=
         ConstantNode one = ConstantNode.forIntegerStamp(stamp, 1, graph);
         if (iv.direction() == Direction.Up) {
-            IntegerArithmeticNode v1 = sub(graph, ConstantNode.forIntegerStamp(stamp, IntegerStamp.defaultMaxValue(stamp.getBits(), stamp.isUnsigned()), graph), sub(graph, iv.strideNode(), one));
+            IntegerArithmeticNode v1 = sub(graph, ConstantNode.forIntegerStamp(stamp, IntegerStamp.defaultMaxValue(stamp.getBits()), graph), sub(graph, iv.strideNode(), one));
             if (oneOff) {
                 v1 = sub(graph, v1, one);
             }
             cond = graph.unique(new IntegerLessThanNode(v1, end));
         } else {
             assert iv.direction() == Direction.Down;
-            IntegerArithmeticNode v1 = add(graph, ConstantNode.forIntegerStamp(stamp, IntegerStamp.defaultMinValue(stamp.getBits(), stamp.isUnsigned()), graph), sub(graph, one, iv.strideNode()));
+            IntegerArithmeticNode v1 = add(graph, ConstantNode.forIntegerStamp(stamp, IntegerStamp.defaultMinValue(stamp.getBits()), graph), sub(graph, one, iv.strideNode()));
             if (oneOff) {
                 v1 = add(graph, v1, one);
             }
diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.loop/src/com/oracle/graal/loop/DerivedOffsetInductionVariable.java
--- a/graal/com.oracle.graal.loop/src/com/oracle/graal/loop/DerivedOffsetInductionVariable.java	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.loop/src/com/oracle/graal/loop/DerivedOffsetInductionVariable.java	Mon Apr 28 11:18:15 2014 +0200
@@ -22,10 +22,10 @@
  */
 package com.oracle.graal.loop;
 
-import com.oracle.graal.graph.*;
+import com.oracle.graal.compiler.common.*;
+import com.oracle.graal.compiler.common.type.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.calc.*;
-import com.oracle.graal.nodes.type.*;
 
 public class DerivedOffsetInductionVariable extends InductionVariable {
 
diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.loop/src/com/oracle/graal/loop/DerivedScaledInductionVariable.java
--- a/graal/com.oracle.graal.loop/src/com/oracle/graal/loop/DerivedScaledInductionVariable.java	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.loop/src/com/oracle/graal/loop/DerivedScaledInductionVariable.java	Mon Apr 28 11:18:15 2014 +0200
@@ -22,9 +22,9 @@
  */
 package com.oracle.graal.loop;
 
+import com.oracle.graal.compiler.common.type.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.calc.*;
-import com.oracle.graal.nodes.type.*;
 
 public class DerivedScaledInductionVariable extends InductionVariable {
 
diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.loop/src/com/oracle/graal/loop/InductionVariable.java
--- a/graal/com.oracle.graal.loop/src/com/oracle/graal/loop/InductionVariable.java	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.loop/src/com/oracle/graal/loop/InductionVariable.java	Mon Apr 28 11:18:15 2014 +0200
@@ -22,9 +22,9 @@
  */
 package com.oracle.graal.loop;
 
-import com.oracle.graal.graph.*;
+import com.oracle.graal.compiler.common.*;
+import com.oracle.graal.compiler.common.type.*;
 import com.oracle.graal.nodes.*;
-import com.oracle.graal.nodes.type.*;
 
 /**
  * This class describes a value node that is an induction variable in a counted loop.
diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.loop/src/com/oracle/graal/loop/LoopEx.java
--- a/graal/com.oracle.graal.loop/src/com/oracle/graal/loop/LoopEx.java	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.loop/src/com/oracle/graal/loop/LoopEx.java	Mon Apr 28 11:18:15 2014 +0200
@@ -25,6 +25,9 @@
 import java.util.*;
 
 import com.oracle.graal.api.meta.*;
+import com.oracle.graal.compiler.common.*;
+import com.oracle.graal.compiler.common.calc.*;
+import com.oracle.graal.compiler.common.cfg.*;
 import com.oracle.graal.debug.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.graph.iterators.*;
@@ -36,19 +39,19 @@
 
 public class LoopEx {
 
-    private final Loop lirLoop;
+    private final Loop lirLoop;
     private LoopFragmentInside inside;
     private LoopFragmentWhole whole;
     private CountedLoopInfo counted; // TODO (gd) detect
     private LoopsData data;
     private InductionVariables ivs;
 
-    LoopEx(Loop lirLoop, LoopsData data) {
+    LoopEx(Loop lirLoop, LoopsData data) {
         this.lirLoop = lirLoop;
         this.data = data;
     }
 
-    public Loop lirLoop() {
+    public Loop lirLoop() {
         return lirLoop;
     }
 
@@ -88,7 +91,7 @@
     }
 
     public LoopBeginNode loopBegin() {
-        return lirLoop().loopBegin();
+        return (LoopBeginNode) lirLoop().header.getBeginNode();
     }
 
     public FixedNode predecessor() {
@@ -123,7 +126,7 @@
         return (isCounted() ? "CountedLoop [" + counted() + "] " : "Loop ") + "(depth=" + lirLoop().depth + ") " + loopBegin();
     }
 
-    private class InvariantPredicate extends NodePredicate {
+    private class InvariantPredicate implements NodePredicate {
 
         @Override
         public boolean apply(Node n) {
@@ -222,9 +225,9 @@
         return data;
     }
 
-    public NodeBitMap nodesInLoopFrom(AbstractBeginNode point, AbstractBeginNode until) {
-        Collection blocks = new LinkedList<>();
-        Collection exits = new LinkedList<>();
+    public NodeBitMap nodesInLoopFrom(BeginNode point, BeginNode until) {
+        Collection blocks = new LinkedList<>();
+        Collection exits = new LinkedList<>();
         Queue work = new LinkedList<>();
         ControlFlowGraph cfg = loopsData().controlFlowGraph();
         work.add(cfg.blockFor(point));
@@ -235,7 +238,7 @@
                 continue;
             }
             if (lirLoop().exits.contains(b)) {
-                exits.add(b.getBeginNode());
+                exits.add((LoopExitNode) b.getBeginNode());
             } else if (lirLoop().blocks.contains(b)) {
                 blocks.add(b.getBeginNode());
                 work.addAll(b.getDominated());
diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.loop/src/com/oracle/graal/loop/LoopFragment.java
--- a/graal/com.oracle.graal.loop/src/com/oracle/graal/loop/LoopFragment.java	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.loop/src/com/oracle/graal/loop/LoopFragment.java	Mon Apr 28 11:18:15 2014 +0200
@@ -24,14 +24,14 @@
 
 import java.util.*;
 
+import com.oracle.graal.compiler.common.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.graph.Graph.DuplicationReplacement;
 import com.oracle.graal.graph.iterators.*;
 import com.oracle.graal.nodes.*;
-import com.oracle.graal.nodes.VirtualState.VirtualClosure;
 import com.oracle.graal.nodes.cfg.*;
 import com.oracle.graal.nodes.java.*;
-import com.oracle.graal.nodes.util.*;
+import com.oracle.graal.nodes.spi.*;
 import com.oracle.graal.nodes.virtual.*;
 
 public abstract class LoopFragment {
@@ -79,6 +79,15 @@
         duplicationMap.put(oldNode, newNode);
     }
 
+    /**
+     * Gets the corresponding value in this fragment. Should be called on duplicate fragments with a
+     * node from the original fragment as argument.
+     *
+     * @param b original value
+     * @return corresponding value in the peel
+     */
+    protected abstract ValueNode prim(ValueNode b);
+
     public boolean isDuplicate() {
         return original != null;
     }
@@ -141,13 +150,13 @@
         }
     }
 
-    protected static NodeBitMap computeNodes(Graph graph, Iterable blocks) {
-        return computeNodes(graph, blocks, Collections. emptyList());
+    protected static NodeBitMap computeNodes(Graph graph, Iterable blocks) {
+        return computeNodes(graph, blocks, Collections.emptyList());
     }
 
-    protected static NodeBitMap computeNodes(Graph graph, Iterable blocks, Iterable earlyExits) {
+    protected static NodeBitMap computeNodes(Graph graph, Iterable blocks, Iterable earlyExits) {
         final NodeBitMap nodes = graph.createNodeBitMap(true);
-        for (AbstractBeginNode b : blocks) {
+        for (BeginNode b : blocks) {
             if (b.isDeleted()) {
                 continue;
             }
@@ -156,30 +165,21 @@
                 if (n instanceof Invoke) {
                     nodes.mark(((Invoke) n).callTarget());
                 }
-                if (n instanceof StateSplit) {
-                    FrameState stateAfter = ((StateSplit) n).stateAfter();
-                    if (stateAfter != null) {
-                        nodes.mark(stateAfter);
-                    }
+                if (n instanceof NodeWithState) {
+                    NodeWithState withState = (NodeWithState) n;
+                    withState.states().forEach(state -> state.applyToVirtual(node -> nodes.mark(node)));
                 }
                 nodes.mark(n);
             }
         }
-        for (AbstractBeginNode earlyExit : earlyExits) {
+        for (LoopExitNode earlyExit : earlyExits) {
             if (earlyExit.isDeleted()) {
                 continue;
             }
 
             FrameState stateAfter = earlyExit.stateAfter();
             if (stateAfter != null) {
-                nodes.mark(stateAfter);
-                stateAfter.applyToVirtual(new VirtualClosure() {
-
-                    @Override
-                    public void apply(VirtualState node) {
-                        nodes.mark(node);
-                    }
-                });
+                stateAfter.applyToVirtual(node -> nodes.mark(node));
             }
             nodes.mark(earlyExit);
             for (ProxyNode proxy : earlyExit.proxies()) {
@@ -188,7 +188,7 @@
         }
 
         final NodeBitMap notloopNodes = graph.createNodeBitMap(true);
-        for (AbstractBeginNode b : blocks) {
+        for (BeginNode b : blocks) {
             if (b.isDeleted()) {
                 continue;
             }
@@ -245,19 +245,19 @@
         return false;
     }
 
-    public static NodeIterable toHirBlocks(final Iterable blocks) {
-        return new AbstractNodeIterable() {
+    public static NodeIterable toHirBlocks(final Iterable blocks) {
+        return new NodeIterable() {
 
-            public Iterator iterator() {
+            public Iterator iterator() {
                 final Iterator it = blocks.iterator();
-                return new Iterator() {
+                return new Iterator() {
 
                     @Override
                     public void remove() {
                         throw new UnsupportedOperationException();
                     }
 
-                    public AbstractBeginNode next() {
+                    public BeginNode next() {
                         return it.next().getBeginNode();
                     }
 
@@ -270,6 +270,31 @@
         };
     }
 
+    public static NodeIterable toHirExits(final Iterable blocks) {
+        return new NodeIterable() {
+
+            public Iterator iterator() {
+                final Iterator it = blocks.iterator();
+                return new Iterator() {
+
+                    @Override
+                    public void remove() {
+                        throw new UnsupportedOperationException();
+                    }
+
+                    public LoopExitNode next() {
+                        return (LoopExitNode) it.next().getBeginNode();
+                    }
+
+                    public boolean hasNext() {
+                        return it.hasNext();
+                    }
+                };
+            }
+
+        };
+    }
+
     /**
      * Merges the early exits (i.e. loop exits) that were duplicated as part of this fragment, with
      * the original fragment's exits.
@@ -277,59 +302,56 @@
     protected void mergeEarlyExits() {
         assert isDuplicate();
         StructuredGraph graph = graph();
-        for (AbstractBeginNode earlyExit : LoopFragment.toHirBlocks(original().loop().lirLoop().exits)) {
-            FixedNode next = earlyExit.next();
-            if (earlyExit.isDeleted() || !this.original().contains(earlyExit)) {
+        for (BeginNode earlyExit : LoopFragment.toHirBlocks(original().loop().lirLoop().exits)) {
+            LoopExitNode loopEarlyExit = (LoopExitNode) earlyExit;
+            FixedNode next = loopEarlyExit.next();
+            if (loopEarlyExit.isDeleted() || !this.original().contains(loopEarlyExit)) {
                 continue;
             }
-            AbstractBeginNode newEarlyExit = getDuplicatedNode(earlyExit);
+            BeginNode newEarlyExit = getDuplicatedNode(loopEarlyExit);
             if (newEarlyExit == null) {
                 continue;
             }
-            boolean newEarlyExitIsBegin = newEarlyExit instanceof BeginNode;
             MergeNode merge = graph.add(new MergeNode());
             AbstractEndNode originalEnd = graph.add(new EndNode());
             AbstractEndNode newEnd = graph.add(new EndNode());
             merge.addForwardEnd(originalEnd);
             merge.addForwardEnd(newEnd);
-            earlyExit.setNext(originalEnd);
+            loopEarlyExit.setNext(originalEnd);
             newEarlyExit.setNext(newEnd);
             merge.setNext(next);
 
-            FrameState exitState = earlyExit.stateAfter();
+            FrameState exitState = loopEarlyExit.stateAfter();
             FrameState state = null;
             if (exitState != null) {
                 state = exitState;
                 exitState = exitState.duplicateWithVirtualState();
-                earlyExit.setStateAfter(exitState);
+                loopEarlyExit.setStateAfter(exitState);
                 merge.setStateAfter(state);
                 /*
                  * Using the old exit's state as the merge's state is necessary because some of the
                  * VirtualState nodes contained in the old exit's state may be shared by other
                  * dominated VirtualStates. Those dominated virtual states need to see the
                  * proxy->phi update that are applied below.
-                 * 
+                 *
                  * We now update the original fragment's nodes accordingly:
                  */
-                state.applyToVirtual(new VirtualClosure() {
-                    public void apply(VirtualState node) {
-                        original.nodes.clear(node);
-                    }
-                });
-                exitState.applyToVirtual(new VirtualClosure() {
-                    public void apply(VirtualState node) {
-                        original.nodes.mark(node);
-                    }
-                });
+                state.applyToVirtual(node -> original.nodes.clear(node));
+                exitState.applyToVirtual(node -> original.nodes.mark(node));
+            }
+            FrameState finalExitState = exitState;
+
+            for (Node anchored : loopEarlyExit.anchored().snapshot()) {
+                anchored.replaceFirstInput(loopEarlyExit, merge);
             }
 
-            for (Node anchored : earlyExit.anchored().snapshot()) {
-                anchored.replaceFirstInput(earlyExit, merge);
-            }
-
-            for (final ProxyNode vpn : earlyExit.proxies().snapshot()) {
+            boolean newEarlyExitIsLoopExit = newEarlyExit instanceof LoopExitNode;
+            for (final ProxyNode vpn : loopEarlyExit.proxies().snapshot()) {
+                if (vpn.usages().isEmpty()) {
+                    continue;
+                }
                 final ValueNode replaceWith;
-                ProxyNode newVpn = getDuplicatedNode(vpn);
+                ValueNode newVpn = prim(newEarlyExitIsLoopExit ? vpn : vpn.value());
                 if (newVpn != null) {
                     PhiNode phi;
                     if (vpn instanceof ValueProxyNode) {
@@ -342,32 +364,23 @@
                         throw GraalInternalError.shouldNotReachHere();
                     }
                     phi.addInput(vpn);
-                    phi.addInput(newEarlyExitIsBegin ? newVpn.value() : newVpn);
+                    phi.addInput(newVpn);
                     replaceWith = phi;
                 } else {
                     replaceWith = vpn.value();
                 }
-                for (Node usage : vpn.usages().snapshot()) {
-                    if (!merge.isPhiAtMerge(usage)) {
-                        if (usage instanceof VirtualState) {
-                            VirtualState stateUsage = (VirtualState) usage;
-                            if (exitState.isPartOfThisState(stateUsage)) {
-                                continue;
-                            }
-                        }
-                        usage.replaceFirstInput(vpn, replaceWith);
+                vpn.replaceAtMatchingUsages(replaceWith, usage -> {
+                    if (merge.isPhiAtMerge(usage)) {
+                        return false;
                     }
-                }
-            }
-            if (newEarlyExitIsBegin) {
-                FrameState stateAtNewEarlyExit = newEarlyExit.stateAfter();
-                if (stateAtNewEarlyExit != null) {
-                    newEarlyExit.setStateAfter(null);
-                    GraphUtil.killWithUnusedFloatingInputs(stateAtNewEarlyExit);
-                }
-                for (ProxyNode proxy : newEarlyExit.proxies().snapshot()) {
-                    GraphUtil.killWithUnusedFloatingInputs(proxy);
-                }
+                    if (usage instanceof VirtualState) {
+                        VirtualState stateUsage = (VirtualState) usage;
+                        if (finalExitState.isPartOfThisState(stateUsage)) {
+                            return false;
+                        }
+                    }
+                    return true;
+                });
             }
         }
     }
diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.loop/src/com/oracle/graal/loop/LoopFragmentInside.java
--- a/graal/com.oracle.graal.loop/src/com/oracle/graal/loop/LoopFragmentInside.java	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.loop/src/com/oracle/graal/loop/LoopFragmentInside.java	Mon Apr 28 11:18:15 2014 +0200
@@ -24,12 +24,12 @@
 
 import java.util.*;
 
+import com.oracle.graal.compiler.common.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.graph.Graph.DuplicationReplacement;
 import com.oracle.graal.graph.iterators.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.VirtualState.NodeClosure;
-import com.oracle.graal.nodes.util.*;
 
 public class LoopFragmentInside extends LoopFragment {
 
@@ -88,18 +88,13 @@
 
         patchNodes(dataFixBefore);
 
-        AbstractBeginNode end = mergeEnds();
-
-        original().patchPeeling(this);
+        BeginNode end = mergeEnds();
 
         mergeEarlyExits();
 
-        AbstractBeginNode entry = getDuplicatedNode(loop.loopBegin());
-        FrameState state = entry.stateAfter();
-        if (state != null) {
-            entry.setStateAfter(null);
-            GraphUtil.killWithUnusedFloatingInputs(state);
-        }
+        original().patchPeeling(this);
+
+        BeginNode entry = getDuplicatedNode(loop.loopBegin());
         loop.entryPoint().replaceAtPredecessor(entry);
         end.setNext(loop.entryPoint());
     }
@@ -111,13 +106,31 @@
             whole.nodes(); // init nodes bitmap in whole
             nodes = whole.nodes.copy();
             // remove the phis
-            for (PhiNode phi : loop().loopBegin().phis()) {
+            LoopBeginNode loopBegin = loop().loopBegin();
+            for (PhiNode phi : loopBegin.phis()) {
                 nodes.clear(phi);
             }
+            for (LoopExitNode exit : exits()) {
+                FrameState exitState = exit.stateAfter();
+                if (exitState != null) {
+                    exitState.applyToVirtual(v -> {
+                        if (v.usages().filter(n -> nodes.isMarked(n) && n != exit).isEmpty()) {
+                            nodes.clear(v);
+                        }
+                    });
+                }
+                for (ProxyNode proxy : exit.proxies()) {
+                    nodes.clear(proxy);
+                }
+            }
         }
         return nodes;
     }
 
+    public NodeIterable exits() {
+        return loop().loopBegin().loopExits();
+    }
+
     @Override
     protected DuplicationReplacement getDuplicationReplacement() {
         final LoopBeginNode loopBegin = loop().loopBegin();
@@ -183,7 +196,22 @@
         LoopBeginNode loopBegin = loop().loopBegin();
         StructuredGraph graph = loopBegin.graph();
         List newPhis = new LinkedList<>();
+
+        NodeBitMap usagesToPatch = nodes.copy();
+        for (LoopExitNode exit : exits()) {
+            FrameState exitState = exit.stateAfter();
+            if (exitState != null) {
+                exitState.applyToVirtual(v -> usagesToPatch.mark(v));
+            }
+            for (ProxyNode proxy : exit.proxies()) {
+                usagesToPatch.mark(proxy);
+            }
+        }
+
         for (PhiNode phi : loopBegin.phis().snapshot()) {
+            if (phi.usages().isEmpty()) {
+                continue;
+            }
             ValueNode first;
             if (loopBegin.loopEnds().count() == 1) {
                 ValueNode b = phi.valueAt(loopBegin.loopEnds().first()); // back edge value
@@ -201,9 +229,8 @@
             peel.putDuplicatedNode(phi, newPhi);
             newPhis.add(newPhi);
             for (Node usage : phi.usages().snapshot()) {
-                if (peel.getDuplicatedNode(usage) != null) { // patch only usages that should use
-                                                             // the new phi ie usages that were
-                                                             // peeled
+                // patch only usages that should use the new phi ie usages that were peeled
+                if (usagesToPatch.isMarked(usage)) {
                     usage.replaceFirstInput(phi, newPhi);
                 }
             }
@@ -229,7 +256,8 @@
      * @param b original value
      * @return corresponding value in the peel
      */
-    private ValueNode prim(ValueNode b) {
+    @Override
+    protected ValueNode prim(ValueNode b) {
         assert isDuplicate();
         LoopBeginNode loopBegin = original().loop().loopBegin();
         if (loopBegin.isPhiAtMerge(b)) {
@@ -246,7 +274,7 @@
         }
     }
 
-    private AbstractBeginNode mergeEnds() {
+    private BeginNode mergeEnds() {
         assert isDuplicate();
         List endsToMerge = new LinkedList<>();
         Map reverseEnds = new HashMap<>(); // map peel's exit to the
@@ -260,7 +288,7 @@
             }
         }
         mergedInitializers = new IdentityHashMap<>();
-        AbstractBeginNode newExit;
+        BeginNode newExit;
         StructuredGraph graph = graph();
         if (endsToMerge.size() == 1) {
             AbstractEndNode end = endsToMerge.get(0);
@@ -283,6 +311,9 @@
             }
 
             for (final PhiNode phi : loopBegin.phis().snapshot()) {
+                if (phi.usages().isEmpty()) {
+                    continue;
+                }
                 final PhiNode firstPhi = patchPhi(graph, phi, newExitMerge);
                 for (AbstractEndNode end : newExitMerge.forwardEnds()) {
                     LoopEndNode loopEnd = reverseEnds.get(end);
diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.loop/src/com/oracle/graal/loop/LoopFragmentWhole.java
--- a/graal/com.oracle.graal.loop/src/com/oracle/graal/loop/LoopFragmentWhole.java	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.loop/src/com/oracle/graal/loop/LoopFragmentWhole.java	Mon Apr 28 11:18:15 2014 +0200
@@ -22,6 +22,7 @@
  */
 package com.oracle.graal.loop;
 
+import com.oracle.graal.compiler.common.cfg.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.graph.Graph.DuplicationReplacement;
 import com.oracle.graal.graph.iterators.*;
@@ -56,13 +57,18 @@
     @Override
     public NodeIterable nodes() {
         if (nodes == null) {
-            Loop lirLoop = loop().lirLoop();
-            nodes = LoopFragment.computeNodes(graph(), LoopFragment.toHirBlocks(lirLoop.blocks), LoopFragment.toHirBlocks(lirLoop.exits));
+            Loop lirLoop = loop().lirLoop();
+            nodes = LoopFragment.computeNodes(graph(), LoopFragment.toHirBlocks(lirLoop.blocks), LoopFragment.toHirExits(lirLoop.exits));
         }
         return nodes;
     }
 
     @Override
+    protected ValueNode prim(ValueNode b) {
+        return getDuplicatedNode(b);
+    }
+
+    @Override
     protected DuplicationReplacement getDuplicationReplacement() {
         final FixedNode entry = loop().entryPoint();
         final Graph graph = this.graph();
diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.loop/src/com/oracle/graal/loop/LoopPolicies.java
--- a/graal/com.oracle.graal.loop/src/com/oracle/graal/loop/LoopPolicies.java	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.loop/src/com/oracle/graal/loop/LoopPolicies.java	Mon Apr 28 11:18:15 2014 +0200
@@ -22,7 +22,7 @@
  */
 package com.oracle.graal.loop;
 
-import static com.oracle.graal.phases.GraalOptions.*;
+import static com.oracle.graal.compiler.common.GraalOptions.*;
 
 import com.oracle.graal.debug.*;
 import com.oracle.graal.graph.*;
@@ -64,12 +64,12 @@
 
     public static boolean shouldUnswitch(LoopEx loop, ControlSplitNode controlSplit) {
         Block postDomBlock = loop.loopsData().controlFlowGraph().blockFor(controlSplit).getPostdominator();
-        AbstractBeginNode postDom = postDomBlock != null ? postDomBlock.getBeginNode() : null;
+        BeginNode postDom = postDomBlock != null ? postDomBlock.getBeginNode() : null;
         int loopTotal = loop.size();
         int inBranchTotal = 0;
         double maxProbability = 0;
         for (Node successor : controlSplit.successors()) {
-            AbstractBeginNode branch = (AbstractBeginNode) successor;
+            BeginNode branch = (BeginNode) successor;
             inBranchTotal += loop.nodesInLoopFrom(branch, postDom).cardinality(); // this may count
                                                                                   // twice because
                                                                                   // of fall-through
diff -r 3dde8d8c95b8 -r 40d0022115ee 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	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.loop/src/com/oracle/graal/loop/LoopTransformations.java	Mon Apr 28 11:18:15 2014 +0200
@@ -22,7 +22,7 @@
  */
 package com.oracle.graal.loop;
 
-import static com.oracle.graal.phases.GraalOptions.*;
+import static com.oracle.graal.compiler.common.GraalOptions.*;
 
 import com.oracle.graal.api.code.*;
 import com.oracle.graal.graph.Graph.Mark;
@@ -63,6 +63,7 @@
             Mark mark = graph.getMark();
             peel(loop);
             canonicalizer.applyIncremental(graph, context, mark);
+            loopBegin.removeDeadPhis();
             loop.invalidateFragments();
             if (iterations++ > UNROLL_LIMIT || graph.getNodeCount() > MaximumDesiredSize.getValue() * 3) {
                 throw new BailoutException("FullUnroll : Graph seems to grow out of proportion");
@@ -81,19 +82,19 @@
         // original loop is used as first successor
         Position firstPosition = successors.nextPosition();
         NodeClass controlSplitClass = controlSplitNode.getNodeClass();
-        controlSplitClass.set(newControlSplit, firstPosition, AbstractBeginNode.begin(originalLoop.entryPoint()));
+        controlSplitClass.set(newControlSplit, firstPosition, BeginNode.begin(originalLoop.entryPoint()));
 
         StructuredGraph graph = controlSplitNode.graph();
         while (successors.hasNext()) {
             Position position = successors.nextPosition();
             // create a new loop duplicate, connect it and simplify it
             LoopFragmentWhole duplicateLoop = originalLoop.duplicate();
-            controlSplitClass.set(newControlSplit, position, AbstractBeginNode.begin(duplicateLoop.entryPoint()));
+            controlSplitClass.set(newControlSplit, position, BeginNode.begin(duplicateLoop.entryPoint()));
             ControlSplitNode duplicatedControlSplit = duplicateLoop.getDuplicatedNode(controlSplitNode);
-            graph.removeSplitPropagate(duplicatedControlSplit, (AbstractBeginNode) controlSplitClass.get(duplicatedControlSplit, position));
+            graph.removeSplitPropagate(duplicatedControlSplit, (BeginNode) controlSplitClass.get(duplicatedControlSplit, position));
         }
         // original loop is simplified last to avoid deleting controlSplitNode too early
-        graph.removeSplitPropagate(controlSplitNode, (AbstractBeginNode) controlSplitClass.get(controlSplitNode, firstPosition));
+        graph.removeSplitPropagate(controlSplitNode, (BeginNode) controlSplitClass.get(controlSplitNode, firstPosition));
         // TODO (gd) probabilities need some amount of fixup.. (probably also in other transforms)
     }
 
diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.loop/src/com/oracle/graal/loop/LoopsData.java
--- a/graal/com.oracle.graal.loop/src/com/oracle/graal/loop/LoopsData.java	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.loop/src/com/oracle/graal/loop/LoopsData.java	Mon Apr 28 11:18:15 2014 +0200
@@ -24,6 +24,7 @@
 
 import java.util.*;
 
+import com.oracle.graal.compiler.common.cfg.*;
 import com.oracle.graal.debug.*;
 import com.oracle.graal.debug.Debug.Scope;
 import com.oracle.graal.nodes.*;
@@ -31,7 +32,7 @@
 
 public class LoopsData {
 
-    private Map lirLoopToEx = new IdentityHashMap<>();
+    private Map, LoopEx> lirLoopToEx = new IdentityHashMap<>();
     private Map loopBeginToEx = new IdentityHashMap<>();
     private ControlFlowGraph cfg;
 
@@ -42,14 +43,14 @@
             throw Debug.handle(e);
         }
 
-        for (Loop lirLoop : cfg.getLoops()) {
+        for (Loop lirLoop : cfg.getLoops()) {
             LoopEx ex = new LoopEx(lirLoop, this);
             lirLoopToEx.put(lirLoop, ex);
             loopBeginToEx.put(ex.loopBegin(), ex);
         }
     }
 
-    public LoopEx loop(Loop lirLoop) {
+    public LoopEx loop(Loop lirLoop) {
         return lirLoopToEx.get(lirLoop);
     }
 
diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.loop/src/com/oracle/graal/loop/phases/LoopTransformHighPhase.java
--- a/graal/com.oracle.graal.loop/src/com/oracle/graal/loop/phases/LoopTransformHighPhase.java	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.loop/src/com/oracle/graal/loop/phases/LoopTransformHighPhase.java	Mon Apr 28 11:18:15 2014 +0200
@@ -22,7 +22,7 @@
  */
 package com.oracle.graal.loop.phases;
 
-import static com.oracle.graal.phases.GraalOptions.*;
+import static com.oracle.graal.compiler.common.GraalOptions.*;
 
 import com.oracle.graal.debug.*;
 import com.oracle.graal.loop.*;
diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.loop/src/com/oracle/graal/loop/phases/LoopTransformLowPhase.java
--- a/graal/com.oracle.graal.loop/src/com/oracle/graal/loop/phases/LoopTransformLowPhase.java	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.loop/src/com/oracle/graal/loop/phases/LoopTransformLowPhase.java	Mon Apr 28 11:18:15 2014 +0200
@@ -22,7 +22,7 @@
  */
 package com.oracle.graal.loop.phases;
 
-import static com.oracle.graal.phases.GraalOptions.*;
+import static com.oracle.graal.compiler.common.GraalOptions.*;
 
 import com.oracle.graal.debug.*;
 import com.oracle.graal.debug.Debug.Scope;
@@ -78,7 +78,7 @@
         sb.append(loop).append(" at ").append(controlSplit).append(" [");
         NodeClassIterator it = controlSplit.successors().iterator();
         while (it.hasNext()) {
-            sb.append(controlSplit.probability((AbstractBeginNode) it.next()));
+            sb.append(controlSplit.probability((BeginNode) it.next()));
             if (it.hasNext()) {
                 sb.append(", ");
             }
diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.nodes.test/src/com/oracle/graal/nodes/test/IntegerStampTest.java
--- a/graal/com.oracle.graal.nodes.test/src/com/oracle/graal/nodes/test/IntegerStampTest.java	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.nodes.test/src/com/oracle/graal/nodes/test/IntegerStampTest.java	Mon Apr 28 11:18:15 2014 +0200
@@ -27,6 +27,7 @@
 import org.junit.*;
 
 import com.oracle.graal.api.meta.*;
+import com.oracle.graal.compiler.common.type.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.type.*;
 
@@ -44,83 +45,83 @@
 
     @Test
     public void testBooleanConstant() {
-        assertEquals(new IntegerStamp(32, false, 1, 1, 0x1, 0x1), ConstantNode.forBoolean(true, graph).stamp());
-        assertEquals(new IntegerStamp(32, false, 0, 0, 0x0, 0x0), ConstantNode.forBoolean(false, graph).stamp());
+        assertEquals(new IntegerStamp(32, 1, 1, 0x1, 0x1), ConstantNode.forBoolean(true, graph).stamp());
+        assertEquals(new IntegerStamp(32, 0, 0, 0x0, 0x0), ConstantNode.forBoolean(false, graph).stamp());
     }
 
     @Test
     public void testByteConstant() {
-        assertEquals(new IntegerStamp(32, false, 0, 0, 0x0, 0x0), ConstantNode.forByte((byte) 0, graph).stamp());
-        assertEquals(new IntegerStamp(32, false, 16, 16, 0x10, 0x10), ConstantNode.forByte((byte) 16, graph).stamp());
-        assertEquals(new IntegerStamp(32, false, -16, -16, 0xfffffff0L, 0xfffffff0L), ConstantNode.forByte((byte) -16, graph).stamp());
-        assertEquals(new IntegerStamp(32, false, 127, 127, 0x7f, 0x7f), ConstantNode.forByte((byte) 127, graph).stamp());
-        assertEquals(new IntegerStamp(32, false, -128, -128, 0xffffff80L, 0xffffff80L), ConstantNode.forByte((byte) -128, graph).stamp());
+        assertEquals(new IntegerStamp(32, 0, 0, 0x0, 0x0), ConstantNode.forByte((byte) 0, graph).stamp());
+        assertEquals(new IntegerStamp(32, 16, 16, 0x10, 0x10), ConstantNode.forByte((byte) 16, graph).stamp());
+        assertEquals(new IntegerStamp(32, -16, -16, 0xfffffff0L, 0xfffffff0L), ConstantNode.forByte((byte) -16, graph).stamp());
+        assertEquals(new IntegerStamp(32, 127, 127, 0x7f, 0x7f), ConstantNode.forByte((byte) 127, graph).stamp());
+        assertEquals(new IntegerStamp(32, -128, -128, 0xffffff80L, 0xffffff80L), ConstantNode.forByte((byte) -128, graph).stamp());
     }
 
     @Test
     public void testShortConstant() {
-        assertEquals(new IntegerStamp(32, false, 0, 0, 0x0, 0x0), ConstantNode.forShort((short) 0, graph).stamp());
-        assertEquals(new IntegerStamp(32, false, 128, 128, 0x80, 0x80), ConstantNode.forShort((short) 128, graph).stamp());
-        assertEquals(new IntegerStamp(32, false, -128, -128, 0xffffff80L, 0xffffff80L), ConstantNode.forShort((short) -128, graph).stamp());
-        assertEquals(new IntegerStamp(32, false, 32767, 32767, 0x7fff, 0x7fff), ConstantNode.forShort((short) 32767, graph).stamp());
-        assertEquals(new IntegerStamp(32, false, -32768, -32768, 0xffff8000L, 0xffff8000L), ConstantNode.forShort((short) -32768, graph).stamp());
+        assertEquals(new IntegerStamp(32, 0, 0, 0x0, 0x0), ConstantNode.forShort((short) 0, graph).stamp());
+        assertEquals(new IntegerStamp(32, 128, 128, 0x80, 0x80), ConstantNode.forShort((short) 128, graph).stamp());
+        assertEquals(new IntegerStamp(32, -128, -128, 0xffffff80L, 0xffffff80L), ConstantNode.forShort((short) -128, graph).stamp());
+        assertEquals(new IntegerStamp(32, 32767, 32767, 0x7fff, 0x7fff), ConstantNode.forShort((short) 32767, graph).stamp());
+        assertEquals(new IntegerStamp(32, -32768, -32768, 0xffff8000L, 0xffff8000L), ConstantNode.forShort((short) -32768, graph).stamp());
     }
 
     @Test
     public void testCharConstant() {
-        assertEquals(new IntegerStamp(32, false, 0, 0, 0x0, 0x0), ConstantNode.forChar((char) 0, graph).stamp());
-        assertEquals(new IntegerStamp(32, false, 'A', 'A', 'A', 'A'), ConstantNode.forChar('A', graph).stamp());
-        assertEquals(new IntegerStamp(32, false, 128, 128, 0x80, 0x80), ConstantNode.forChar((char) 128, graph).stamp());
-        assertEquals(new IntegerStamp(32, false, 65535, 65535, 0xffff, 0xffff), ConstantNode.forChar((char) 65535, graph).stamp());
+        assertEquals(new IntegerStamp(32, 0, 0, 0x0, 0x0), ConstantNode.forChar((char) 0, graph).stamp());
+        assertEquals(new IntegerStamp(32, 'A', 'A', 'A', 'A'), ConstantNode.forChar('A', graph).stamp());
+        assertEquals(new IntegerStamp(32, 128, 128, 0x80, 0x80), ConstantNode.forChar((char) 128, graph).stamp());
+        assertEquals(new IntegerStamp(32, 65535, 65535, 0xffff, 0xffff), ConstantNode.forChar((char) 65535, graph).stamp());
     }
 
     @Test
     public void testIntConstant() {
-        assertEquals(new IntegerStamp(32, false, 0, 0, 0x0, 0x0), ConstantNode.forInt(0, graph).stamp());
-        assertEquals(new IntegerStamp(32, false, 128, 128, 0x80, 0x80), ConstantNode.forInt(128, graph).stamp());
-        assertEquals(new IntegerStamp(32, false, -128, -128, 0xffffff80L, 0xffffff80L), ConstantNode.forInt(-128, graph).stamp());
-        assertEquals(new IntegerStamp(32, false, Integer.MAX_VALUE, Integer.MAX_VALUE, 0x7fffffff, 0x7fffffff), ConstantNode.forInt(Integer.MAX_VALUE, graph).stamp());
-        assertEquals(new IntegerStamp(32, false, Integer.MIN_VALUE, Integer.MIN_VALUE, 0x80000000L, 0x80000000L), ConstantNode.forInt(Integer.MIN_VALUE, graph).stamp());
+        assertEquals(new IntegerStamp(32, 0, 0, 0x0, 0x0), ConstantNode.forInt(0, graph).stamp());
+        assertEquals(new IntegerStamp(32, 128, 128, 0x80, 0x80), ConstantNode.forInt(128, graph).stamp());
+        assertEquals(new IntegerStamp(32, -128, -128, 0xffffff80L, 0xffffff80L), ConstantNode.forInt(-128, graph).stamp());
+        assertEquals(new IntegerStamp(32, Integer.MAX_VALUE, Integer.MAX_VALUE, 0x7fffffff, 0x7fffffff), ConstantNode.forInt(Integer.MAX_VALUE, graph).stamp());
+        assertEquals(new IntegerStamp(32, Integer.MIN_VALUE, Integer.MIN_VALUE, 0x80000000L, 0x80000000L), ConstantNode.forInt(Integer.MIN_VALUE, graph).stamp());
     }
 
     @Test
     public void testLongConstant() {
-        assertEquals(new IntegerStamp(64, false, 0, 0, 0x0, 0x0), ConstantNode.forLong(0, graph).stamp());
-        assertEquals(new IntegerStamp(64, false, 128, 128, 0x80, 0x80), ConstantNode.forLong(128, graph).stamp());
-        assertEquals(new IntegerStamp(64, false, -128, -128, 0xffffffffffffff80L, 0xffffffffffffff80L), ConstantNode.forLong(-128, graph).stamp());
-        assertEquals(new IntegerStamp(64, false, Long.MAX_VALUE, Long.MAX_VALUE, 0x7fffffffffffffffL, 0x7fffffffffffffffL), ConstantNode.forLong(Long.MAX_VALUE, graph).stamp());
-        assertEquals(new IntegerStamp(64, false, Long.MIN_VALUE, Long.MIN_VALUE, 0x8000000000000000L, 0x8000000000000000L), ConstantNode.forLong(Long.MIN_VALUE, graph).stamp());
+        assertEquals(new IntegerStamp(64, 0, 0, 0x0, 0x0), ConstantNode.forLong(0, graph).stamp());
+        assertEquals(new IntegerStamp(64, 128, 128, 0x80, 0x80), ConstantNode.forLong(128, graph).stamp());
+        assertEquals(new IntegerStamp(64, -128, -128, 0xffffffffffffff80L, 0xffffffffffffff80L), ConstantNode.forLong(-128, graph).stamp());
+        assertEquals(new IntegerStamp(64, Long.MAX_VALUE, Long.MAX_VALUE, 0x7fffffffffffffffL, 0x7fffffffffffffffL), ConstantNode.forLong(Long.MAX_VALUE, graph).stamp());
+        assertEquals(new IntegerStamp(64, Long.MIN_VALUE, Long.MIN_VALUE, 0x8000000000000000L, 0x8000000000000000L), ConstantNode.forLong(Long.MIN_VALUE, graph).stamp());
     }
 
     @Test
     public void testPositiveRanges() {
-        assertEquals(new IntegerStamp(32, false, 0, 0, 0, 0), StampFactory.forInteger(Kind.Int, 0, 0));
-        assertEquals(new IntegerStamp(32, false, 0, 1, 0, 1), StampFactory.forInteger(Kind.Int, 0, 1));
-        assertEquals(new IntegerStamp(32, false, 0, 0x123, 0, 0x1ff), StampFactory.forInteger(Kind.Int, 0, 0x123));
-        assertEquals(new IntegerStamp(32, false, 0x120, 0x123, 0x120, 0x123), StampFactory.forInteger(Kind.Int, 0x120, 0x123));
-        assertEquals(new IntegerStamp(32, false, 10000, 15000, 0x2000, 0x3fff), StampFactory.forInteger(Kind.Int, 10000, 15000));
-        assertEquals(new IntegerStamp(64, false, 0, 1, 0, 1), StampFactory.forInteger(Kind.Long, 0, 1));
-        assertEquals(new IntegerStamp(64, false, 10000, 15000, 0x2000, 0x3fff), StampFactory.forInteger(Kind.Long, 10000, 15000));
-        assertEquals(new IntegerStamp(64, false, 140000000000L, 150000000000L, 0x2000000000L, 0x23ffffffffL), StampFactory.forInteger(Kind.Long, 140000000000L, 150000000000L));
+        assertEquals(new IntegerStamp(32, 0, 0, 0, 0), StampFactory.forInteger(Kind.Int, 0, 0));
+        assertEquals(new IntegerStamp(32, 0, 1, 0, 1), StampFactory.forInteger(Kind.Int, 0, 1));
+        assertEquals(new IntegerStamp(32, 0, 0x123, 0, 0x1ff), StampFactory.forInteger(Kind.Int, 0, 0x123));
+        assertEquals(new IntegerStamp(32, 0x120, 0x123, 0x120, 0x123), StampFactory.forInteger(Kind.Int, 0x120, 0x123));
+        assertEquals(new IntegerStamp(32, 10000, 15000, 0x2000, 0x3fff), StampFactory.forInteger(Kind.Int, 10000, 15000));
+        assertEquals(new IntegerStamp(64, 0, 1, 0, 1), StampFactory.forInteger(Kind.Long, 0, 1));
+        assertEquals(new IntegerStamp(64, 10000, 15000, 0x2000, 0x3fff), StampFactory.forInteger(Kind.Long, 10000, 15000));
+        assertEquals(new IntegerStamp(64, 140000000000L, 150000000000L, 0x2000000000L, 0x23ffffffffL), StampFactory.forInteger(Kind.Long, 140000000000L, 150000000000L));
     }
 
     @Test
     public void testNegativeRanges() {
-        assertEquals(new IntegerStamp(32, false, -2, -1, 0xfffffffeL, 0xffffffffL), StampFactory.forInteger(Kind.Int, -2, -1));
-        assertEquals(new IntegerStamp(32, false, -20, -10, 0xffffffe0L, 0xffffffffL), StampFactory.forInteger(Kind.Int, -20, -10));
-        assertEquals(new IntegerStamp(32, false, -10000, 0, 0, 0xffffffffL), StampFactory.forInteger(Kind.Int, -10000, 0));
-        assertEquals(new IntegerStamp(32, false, -10000, -1, 0xffffc000L, 0xffffffffL), StampFactory.forInteger(Kind.Int, -10000, -1));
-        assertEquals(new IntegerStamp(32, false, -10010, -10000, 0xffffd8e0L, 0xffffd8ffL), StampFactory.forInteger(Kind.Int, -10010, -10000));
-        assertEquals(new IntegerStamp(64, false, -2, -1, 0xfffffffffffffffeL, 0xffffffffffffffffL), StampFactory.forInteger(Kind.Long, -2, -1));
-        assertEquals(new IntegerStamp(64, false, -10010, -10000, 0xffffffffffffd8e0L, 0xffffffffffffd8ffL), StampFactory.forInteger(Kind.Long, -10010, -10000));
-        assertEquals(new IntegerStamp(64, false, -150000000000L, -140000000000L, 0xffffffdc00000000L, 0xffffffdfffffffffL), StampFactory.forInteger(Kind.Long, -150000000000L, -140000000000L));
+        assertEquals(new IntegerStamp(32, -2, -1, 0xfffffffeL, 0xffffffffL), StampFactory.forInteger(Kind.Int, -2, -1));
+        assertEquals(new IntegerStamp(32, -20, -10, 0xffffffe0L, 0xffffffffL), StampFactory.forInteger(Kind.Int, -20, -10));
+        assertEquals(new IntegerStamp(32, -10000, 0, 0, 0xffffffffL), StampFactory.forInteger(Kind.Int, -10000, 0));
+        assertEquals(new IntegerStamp(32, -10000, -1, 0xffffc000L, 0xffffffffL), StampFactory.forInteger(Kind.Int, -10000, -1));
+        assertEquals(new IntegerStamp(32, -10010, -10000, 0xffffd8e0L, 0xffffd8ffL), StampFactory.forInteger(Kind.Int, -10010, -10000));
+        assertEquals(new IntegerStamp(64, -2, -1, 0xfffffffffffffffeL, 0xffffffffffffffffL), StampFactory.forInteger(Kind.Long, -2, -1));
+        assertEquals(new IntegerStamp(64, -10010, -10000, 0xffffffffffffd8e0L, 0xffffffffffffd8ffL), StampFactory.forInteger(Kind.Long, -10010, -10000));
+        assertEquals(new IntegerStamp(64, -150000000000L, -140000000000L, 0xffffffdc00000000L, 0xffffffdfffffffffL), StampFactory.forInteger(Kind.Long, -150000000000L, -140000000000L));
     }
 
     @Test
     public void testMixedRanges() {
-        assertEquals(new IntegerStamp(32, false, -1, 0, 0, 0xffffffffL), StampFactory.forInteger(Kind.Int, -1, 0));
-        assertEquals(new IntegerStamp(32, false, -10000, 1000, 0, 0xffffffffL), StampFactory.forInteger(Kind.Int, -10000, 1000));
-        assertEquals(new IntegerStamp(64, false, -10000, 1000, 0, 0xffffffffffffffffL), StampFactory.forInteger(Kind.Long, -10000, 1000));
+        assertEquals(new IntegerStamp(32, -1, 0, 0, 0xffffffffL), StampFactory.forInteger(Kind.Int, -1, 0));
+        assertEquals(new IntegerStamp(32, -10000, 1000, 0, 0xffffffffL), StampFactory.forInteger(Kind.Int, -10000, 1000));
+        assertEquals(new IntegerStamp(64, -10000, 1000, 0, 0xffffffffffffffffL), StampFactory.forInteger(Kind.Long, -10000, 1000));
     }
 
     @Test
@@ -159,15 +160,15 @@
 
     @Test
     public void testXor() {
-        assertEquals(new IntegerStamp(32, false, 0, 0xff, 0, 0xff), StampTool.xor(new IntegerStamp(32, false, 0, 0, 0, 0), new IntegerStamp(32, false, 0, 0xff, 0, 0xff)));
-        assertEquals(new IntegerStamp(32, false, 0x10, 0x1f, 0x10, 0x1f), StampTool.xor(new IntegerStamp(32, false, 0, 0, 0, 0), new IntegerStamp(32, false, 0x10, 0x1f, 0x10, 0x1f)));
-        assertEquals(new IntegerStamp(32, false, 0x0, 0xf, 0x0, 0xf), StampTool.xor(new IntegerStamp(32, false, 0x10, 0x10, 0x10, 0x10), new IntegerStamp(32, false, 0x10, 0x1f, 0x10, 0x1f)));
-        assertEquals(new IntegerStamp(32, false, 0x10, 0x1f, 0x10, 0x1f), StampTool.xor(new IntegerStamp(32, false, 0x10, 0x10, 0x10, 0x10), new IntegerStamp(32, false, 0x0, 0xf, 0x0, 0xf)));
+        assertEquals(new IntegerStamp(32, 0, 0xff, 0, 0xff), StampTool.xor(new IntegerStamp(32, 0, 0, 0, 0), new IntegerStamp(32, 0, 0xff, 0, 0xff)));
+        assertEquals(new IntegerStamp(32, 0x10, 0x1f, 0x10, 0x1f), StampTool.xor(new IntegerStamp(32, 0, 0, 0, 0), new IntegerStamp(32, 0x10, 0x1f, 0x10, 0x1f)));
+        assertEquals(new IntegerStamp(32, 0x0, 0xf, 0x0, 0xf), StampTool.xor(new IntegerStamp(32, 0x10, 0x10, 0x10, 0x10), new IntegerStamp(32, 0x10, 0x1f, 0x10, 0x1f)));
+        assertEquals(new IntegerStamp(32, 0x10, 0x1f, 0x10, 0x1f), StampTool.xor(new IntegerStamp(32, 0x10, 0x10, 0x10, 0x10), new IntegerStamp(32, 0x0, 0xf, 0x0, 0xf)));
     }
 
     @Test
     public void testNot() {
-        assertEquals(new IntegerStamp(32, false, -11, -1, 0xffff_fff0L, 0xffff_ffffL), StampTool.not(new IntegerStamp(32, false, 0, 10, 0, 0xf)));
+        assertEquals(new IntegerStamp(32, -11, -1, 0xffff_fff0L, 0xffff_ffffL), StampTool.not(new IntegerStamp(32, 0, 10, 0, 0xf)));
     }
 
     @Test
@@ -258,13 +259,13 @@
 
     @Test
     public void testAnd() {
-        assertEquals(new IntegerStamp(32, false, Integer.MIN_VALUE, 0x40000000L, 0, 0xc0000000L), StampTool.and(StampFactory.forKind(Kind.Int), StampFactory.forConstant(Constant.forInt(0xc0000000))));
+        assertEquals(new IntegerStamp(32, Integer.MIN_VALUE, 0x40000000L, 0, 0xc0000000L), StampTool.and(StampFactory.forKind(Kind.Int), StampFactory.forConstant(Constant.forInt(0xc0000000))));
     }
 
     private static void testSignExtendShort(long lower, long upper) {
-        Stamp shortStamp = StampFactory.forInteger(16, false, lower, upper);
+        Stamp shortStamp = StampFactory.forInteger(16, lower, upper);
         Stamp intStamp = StampTool.signExtend(shortStamp, 32);
-        assertEquals(StampFactory.forInteger(32, false, lower, upper), intStamp);
+        assertEquals(StampFactory.forInteger(32, lower, upper), intStamp);
     }
 
     @Test
@@ -278,9 +279,9 @@
     }
 
     private static void testZeroExtendShort(long lower, long upper, long newLower, long newUpper) {
-        Stamp shortStamp = StampFactory.forInteger(16, false, lower, upper);
+        Stamp shortStamp = StampFactory.forInteger(16, lower, upper);
         Stamp intStamp = StampTool.zeroExtend(shortStamp, 32);
-        assertEquals(StampFactory.forInteger(32, false, newLower, newUpper), intStamp);
+        assertEquals(StampFactory.forInteger(32, newLower, newUpper), intStamp);
     }
 
     @Test
@@ -292,36 +293,4 @@
         testZeroExtendShort(-1, 1, 0, 0xFFFF);
         testZeroExtendShort(Short.MIN_VALUE, Short.MAX_VALUE, 0, 0xFFFF);
     }
-
-    private static void testSignExtendChar(long lower, long upper, long newLower, long newUpper) {
-        Stamp charStamp = StampFactory.forInteger(16, true, lower, upper);
-        Stamp uintStamp = StampTool.signExtend(charStamp, 32);
-        assertEquals(StampFactory.forInteger(32, true, newLower, newUpper), uintStamp);
-    }
-
-    @Test
-    public void testSignExtendUnsigned() {
-        testSignExtendChar(5, 7, 5, 7);
-        testSignExtendChar(0, 42, 0, 42);
-        testSignExtendChar(5, 0xF000, 5, 0xFFFFF000L);
-        testSignExtendChar(0, 0xF000, 0, 0xFFFFF000L);
-        testSignExtendChar(0xF000, Character.MAX_VALUE, 0xFFFFF000L, 0xFFFFFFFFL);
-        testSignExtendChar(Character.MIN_VALUE, Character.MAX_VALUE, 0, 0xFFFFFFFFL);
-    }
-
-    private static void testZeroExtendChar(long lower, long upper) {
-        Stamp charStamp = StampFactory.forInteger(16, true, lower, upper);
-        Stamp uintStamp = StampTool.zeroExtend(charStamp, 32);
-        assertEquals(StampFactory.forInteger(32, true, lower, upper), uintStamp);
-    }
-
-    @Test
-    public void testZeroExtendUnsigned() {
-        testZeroExtendChar(5, 7);
-        testZeroExtendChar(0, 42);
-        testZeroExtendChar(5, 0xF000);
-        testZeroExtendChar(0, 0xF000);
-        testZeroExtendChar(0xF000, Character.MAX_VALUE);
-        testZeroExtendChar(Character.MIN_VALUE, Character.MAX_VALUE);
-    }
 }
diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.nodes.test/src/com/oracle/graal/nodes/test/ObjectStampJoinTest.java
--- a/graal/com.oracle.graal.nodes.test/src/com/oracle/graal/nodes/test/ObjectStampJoinTest.java	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.nodes.test/src/com/oracle/graal/nodes/test/ObjectStampJoinTest.java	Mon Apr 28 11:18:15 2014 +0200
@@ -25,6 +25,7 @@
 import org.junit.*;
 
 import com.oracle.graal.api.meta.*;
+import com.oracle.graal.compiler.common.type.*;
 import com.oracle.graal.compiler.test.*;
 import com.oracle.graal.nodes.type.*;
 
@@ -80,7 +81,7 @@
     public void testJoin3() {
         Stamp d = StampFactory.declared(getType(D.class));
         Stamp c = StampFactory.declared(getType(C.class));
-        Assert.assertTrue(ObjectStamp.isObjectAlwaysNull(join(c, d)));
+        Assert.assertTrue(StampTool.isObjectAlwaysNull(join(c, d)));
     }
 
     @Test
@@ -95,9 +96,9 @@
         Stamp dExact = StampFactory.exact(getType(D.class));
         Stamp c = StampFactory.declared(getType(C.class));
         Stamp join = join(c, dExact);
-        Assert.assertTrue(ObjectStamp.isObjectAlwaysNull(join));
-        Assert.assertNull(ObjectStamp.typeOrNull(join));
-        Assert.assertFalse(ObjectStamp.isExactType(join));
+        Assert.assertTrue(StampTool.isObjectAlwaysNull(join));
+        Assert.assertNull(StampTool.typeOrNull(join));
+        Assert.assertFalse(StampTool.isExactType(join));
     }
 
     @Test
@@ -106,8 +107,8 @@
         Stamp alwaysNull = StampFactory.alwaysNull();
         Stamp join = join(alwaysNull, dExactNonNull);
         Assert.assertFalse(join.isLegal());
-        Assert.assertFalse(ObjectStamp.isObjectNonNull(join));
-        Assert.assertFalse(ObjectStamp.isObjectAlwaysNull(join));
+        Assert.assertFalse(StampTool.isObjectNonNull(join));
+        Assert.assertFalse(StampTool.isObjectAlwaysNull(join));
     }
 
     @Test
@@ -115,9 +116,9 @@
         Stamp aExact = StampFactory.exact(getType(A.class));
         Stamp e = StampFactory.declared(getType(E.class));
         Stamp join = join(aExact, e);
-        Assert.assertTrue(ObjectStamp.isObjectAlwaysNull(join));
-        Assert.assertNull(ObjectStamp.typeOrNull(join));
-        Assert.assertFalse(ObjectStamp.isExactType(join));
+        Assert.assertTrue(StampTool.isObjectAlwaysNull(join));
+        Assert.assertNull(StampTool.typeOrNull(join));
+        Assert.assertFalse(StampTool.isExactType(join));
     }
 
     @Test
diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/AbstractBeginNode.java
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/AbstractBeginNode.java	Fri Apr 25 16:21:07 2014 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,194 +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.nodes;
-
-import static com.oracle.graal.graph.iterators.NodePredicates.*;
-
-import java.util.*;
-
-import com.oracle.graal.graph.*;
-import com.oracle.graal.graph.iterators.*;
-import com.oracle.graal.graph.spi.*;
-import com.oracle.graal.nodes.extended.*;
-import com.oracle.graal.nodes.spi.*;
-import com.oracle.graal.nodes.type.*;
-
-@NodeInfo(allowedUsageTypes = {InputType.Guard, InputType.Anchor})
-public abstract class AbstractBeginNode extends FixedWithNextNode implements StateSplit, LIRLowerable, Simplifiable, GuardingNode, AnchoringNode, IterableNodeType {
-
-    @Input(InputType.State) private FrameState stateAfter;
-
-    public FrameState stateAfter() {
-        return stateAfter;
-    }
-
-    public void setStateAfter(FrameState x) {
-        assert x == null || x.isAlive() : "frame state must be in a graph";
-        updateUsages(stateAfter, x);
-        stateAfter = x;
-    }
-
-    public boolean hasSideEffect() {
-        return false;
-    }
-
-    protected AbstractBeginNode() {
-        super(StampFactory.forVoid());
-    }
-
-    protected AbstractBeginNode(Stamp stamp) {
-        super(stamp);
-    }
-
-    public static AbstractBeginNode begin(FixedNode with) {
-        if (with instanceof AbstractBeginNode) {
-            return (AbstractBeginNode) with;
-        }
-        AbstractBeginNode begin = with.graph().add(new BeginNode());
-        begin.setNext(with);
-        return begin;
-    }
-
-    @Override
-    public void simplify(SimplifierTool tool) {
-        FixedNode prev = (FixedNode) this.predecessor();
-        if (prev == null) {
-            // This is the start node.
-        } else if (prev instanceof ControlSplitNode) {
-            // This begin node is necessary.
-        } else {
-            // This begin node can be removed and all guards moved up to the preceding begin node.
-            prepareDelete();
-            tool.addToWorkList(next());
-            graph().removeFixed(this);
-        }
-    }
-
-    public static AbstractBeginNode prevBegin(FixedNode from) {
-        Node prevBegin = from;
-        while (prevBegin != null) {
-            if (prevBegin instanceof AbstractBeginNode) {
-                return (AbstractBeginNode) prevBegin;
-            }
-            prevBegin = prevBegin.predecessor();
-        }
-        return null;
-    }
-
-    private void evacuateGuards(FixedNode evacuateFrom) {
-        if (!usages().isEmpty()) {
-            AbstractBeginNode prevBegin = prevBegin(evacuateFrom);
-            assert prevBegin != null;
-            for (Node anchored : anchored().snapshot()) {
-                anchored.replaceFirstInput(this, prevBegin);
-            }
-        }
-    }
-
-    public void prepareDelete() {
-        prepareDelete((FixedNode) predecessor());
-    }
-
-    public void prepareDelete(FixedNode evacuateFrom) {
-        removeProxies();
-        evacuateGuards(evacuateFrom);
-    }
-
-    public void removeProxies() {
-        for (ProxyNode vpn : proxies().snapshot()) {
-            // can not use graph.replaceFloating because vpn.value may be null during killCFG
-            vpn.replaceAtUsages(vpn.value());
-            vpn.safeDelete();
-        }
-    }
-
-    @Override
-    public boolean verify() {
-        assertTrue(predecessor() != null || this == graph().start() || this instanceof MergeNode, "begin nodes must be connected");
-        return super.verify();
-    }
-
-    @Override
-    public void generate(NodeLIRBuilderTool gen) {
-        // nop
-    }
-
-    public NodeIterable guards() {
-        return usages().filter(GuardNode.class);
-    }
-
-    public NodeIterable anchored() {
-        return usages().filter(isNotA(ProxyNode.class));
-    }
-
-    public NodeIterable proxies() {
-        return usages().filter(ProxyNode.class);
-    }
-
-    public NodeIterable getBlockNodes() {
-        return new AbstractNodeIterable() {
-
-            @Override
-            public Iterator iterator() {
-                return new BlockNodeIterator(AbstractBeginNode.this);
-            }
-        };
-    }
-
-    private class BlockNodeIterator implements Iterator {
-
-        private FixedNode current;
-
-        public BlockNodeIterator(FixedNode next) {
-            this.current = next;
-        }
-
-        @Override
-        public boolean hasNext() {
-            return current != null;
-        }
-
-        @Override
-        public FixedNode next() {
-            FixedNode ret = current;
-            if (ret == null) {
-                throw new NoSuchElementException();
-            }
-            if (!(current instanceof FixedWithNextNode) || (current instanceof AbstractBeginNode && current != AbstractBeginNode.this)) {
-                current = null;
-            } else {
-                current = ((FixedWithNextNode) current).next();
-            }
-            return ret;
-        }
-
-        @Override
-        public void remove() {
-            throw new UnsupportedOperationException();
-        }
-    }
-
-    public FrameState getState() {
-        return stateAfter();
-    }
-}
diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/AbstractDeoptimizeNode.java
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/AbstractDeoptimizeNode.java	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/AbstractDeoptimizeNode.java	Mon Apr 28 11:18:15 2014 +0200
@@ -23,8 +23,8 @@
 package com.oracle.graal.nodes;
 
 import com.oracle.graal.api.meta.*;
+import com.oracle.graal.compiler.common.type.*;
 import com.oracle.graal.graph.*;
-import com.oracle.graal.nodes.type.*;
 
 /**
  * This node represents an unconditional explicit request for immediate deoptimization.
diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/AbstractEndNode.java
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/AbstractEndNode.java	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/AbstractEndNode.java	Mon Apr 28 11:18:15 2014 +0200
@@ -24,9 +24,9 @@
 
 import java.util.*;
 
+import com.oracle.graal.compiler.common.type.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.nodes.spi.*;
-import com.oracle.graal.nodes.type.*;
 
 public abstract class AbstractEndNode extends FixedNode implements IterableNodeType, LIRLowerable {
 
diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/AbstractFixedGuardNode.java
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/AbstractFixedGuardNode.java	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/AbstractFixedGuardNode.java	Mon Apr 28 11:18:15 2014 +0200
@@ -23,10 +23,10 @@
 package com.oracle.graal.nodes;
 
 import com.oracle.graal.api.meta.*;
+import com.oracle.graal.compiler.common.type.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.graph.spi.*;
 import com.oracle.graal.nodes.extended.*;
-import com.oracle.graal.nodes.type.*;
 import com.oracle.graal.nodes.util.*;
 
 public abstract class AbstractFixedGuardNode extends DeoptimizingFixedWithNextNode implements Simplifiable, GuardingNode {
@@ -89,7 +89,7 @@
         DeoptimizeNode deopt = graph().add(new DeoptimizeNode(action, reason));
         deopt.setStateBefore(stateBefore());
         IfNode ifNode;
-        AbstractBeginNode noDeoptSuccessor;
+        BeginNode noDeoptSuccessor;
         if (negated) {
             ifNode = graph().add(new IfNode(condition, deopt, next, 0));
             noDeoptSuccessor = ifNode.falseSuccessor();
diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/AbstractLocalNode.java
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/AbstractLocalNode.java	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/AbstractLocalNode.java	Mon Apr 28 11:18:15 2014 +0200
@@ -22,8 +22,8 @@
  */
 package com.oracle.graal.nodes;
 
+import com.oracle.graal.compiler.common.type.*;
 import com.oracle.graal.nodes.calc.*;
-import com.oracle.graal.nodes.type.*;
 
 public abstract class AbstractLocalNode extends FloatingNode {
 
diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/AbstractMemoryCheckpoint.java
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/AbstractMemoryCheckpoint.java	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/AbstractMemoryCheckpoint.java	Mon Apr 28 11:18:15 2014 +0200
@@ -22,8 +22,8 @@
  */
 package com.oracle.graal.nodes;
 
+import com.oracle.graal.compiler.common.type.*;
 import com.oracle.graal.nodes.extended.*;
-import com.oracle.graal.nodes.type.*;
 
 /**
  * Provides an implementation of {@link StateSplit}.
diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/AbstractStateSplit.java
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/AbstractStateSplit.java	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/AbstractStateSplit.java	Mon Apr 28 11:18:15 2014 +0200
@@ -22,8 +22,8 @@
  */
 package com.oracle.graal.nodes;
 
+import com.oracle.graal.compiler.common.type.*;
 import com.oracle.graal.graph.*;
-import com.oracle.graal.nodes.type.*;
 
 /**
  * Provides an implementation of {@link StateSplit}.
diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/BeginNode.java
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/BeginNode.java	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/BeginNode.java	Mon Apr 28 11:18:15 2014 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013, 2013, Oracle and/or its affiliates. All rights reserved.
+ * 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
@@ -22,11 +22,153 @@
  */
 package com.oracle.graal.nodes;
 
-import com.oracle.graal.nodes.type.*;
+import static com.oracle.graal.graph.iterators.NodePredicates.*;
+
+import java.util.*;
 
-public final class BeginNode extends AbstractBeginNode {
+import com.oracle.graal.compiler.common.type.*;
+import com.oracle.graal.graph.*;
+import com.oracle.graal.graph.iterators.*;
+import com.oracle.graal.graph.spi.*;
+import com.oracle.graal.nodes.extended.*;
+import com.oracle.graal.nodes.spi.*;
+
+@NodeInfo(allowedUsageTypes = {InputType.Guard, InputType.Anchor})
+public class BeginNode extends FixedWithNextNode implements LIRLowerable, Simplifiable, GuardingNode, AnchoringNode, IterableNodeType {
 
     public BeginNode() {
         super(StampFactory.forVoid());
     }
+
+    public BeginNode(Stamp stamp) {
+        super(stamp);
+    }
+
+    public static BeginNode begin(FixedNode with) {
+        if (with instanceof BeginNode) {
+            return (BeginNode) with;
+        }
+        BeginNode begin = with.graph().add(new BeginNode());
+        begin.setNext(with);
+        return begin;
+    }
+
+    @Override
+    public void simplify(SimplifierTool tool) {
+        FixedNode prev = (FixedNode) this.predecessor();
+        if (prev == null) {
+            // This is the start node.
+        } else if (prev instanceof ControlSplitNode) {
+            // This begin node is necessary.
+        } else {
+            // This begin node can be removed and all guards moved up to the preceding begin node.
+            prepareDelete();
+            tool.addToWorkList(next());
+            graph().removeFixed(this);
+        }
+    }
+
+    public static BeginNode prevBegin(FixedNode from) {
+        Node prevBegin = from;
+        while (prevBegin != null) {
+            if (prevBegin instanceof BeginNode) {
+                return (BeginNode) prevBegin;
+            }
+            prevBegin = prevBegin.predecessor();
+        }
+        return null;
+    }
+
+    private void evacuateGuards(FixedNode evacuateFrom) {
+        if (!usages().isEmpty()) {
+            BeginNode prevBegin = prevBegin(evacuateFrom);
+            assert prevBegin != null;
+            for (Node anchored : anchored().snapshot()) {
+                anchored.replaceFirstInput(this, prevBegin);
+            }
+        }
+    }
+
+    public void prepareDelete() {
+        prepareDelete((FixedNode) predecessor());
+    }
+
+    public void prepareDelete(FixedNode evacuateFrom) {
+        removeProxies();
+        evacuateGuards(evacuateFrom);
+    }
+
+    public void removeProxies() {
+        for (ProxyNode vpn : proxies().snapshot()) {
+            // can not use graph.replaceFloating because vpn.value may be null during killCFG
+            vpn.replaceAtUsages(vpn.value());
+            vpn.safeDelete();
+        }
+    }
+
+    @Override
+    public boolean verify() {
+        assertTrue(predecessor() != null || this == graph().start() || this instanceof MergeNode, "begin nodes must be connected");
+        return super.verify();
+    }
+
+    @Override
+    public void generate(NodeLIRBuilderTool gen) {
+        // nop
+    }
+
+    public NodeIterable guards() {
+        return usages().filter(GuardNode.class);
+    }
+
+    public NodeIterable anchored() {
+        return usages().filter(isNotA(ProxyNode.class));
+    }
+
+    public NodeIterable proxies() {
+        return usages().filter(ProxyNode.class);
+    }
+
+    public NodeIterable getBlockNodes() {
+        return new NodeIterable() {
+
+            @Override
+            public Iterator iterator() {
+                return new BlockNodeIterator(BeginNode.this);
+            }
+        };
+    }
+
+    private class BlockNodeIterator implements Iterator {
+
+        private FixedNode current;
+
+        public BlockNodeIterator(FixedNode next) {
+            this.current = next;
+        }
+
+        @Override
+        public boolean hasNext() {
+            return current != null;
+        }
+
+        @Override
+        public FixedNode next() {
+            FixedNode ret = current;
+            if (ret == null) {
+                throw new NoSuchElementException();
+            }
+            if (!(current instanceof FixedWithNextNode) || (current instanceof BeginNode && current != BeginNode.this)) {
+                current = null;
+            } else {
+                current = ((FixedWithNextNode) current).next();
+            }
+            return ret;
+        }
+
+        @Override
+        public void remove() {
+            throw new UnsupportedOperationException();
+        }
+    }
 }
diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/BeginStateSplitNode.java
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/BeginStateSplitNode.java	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/BeginStateSplitNode.java	Mon Apr 28 11:18:15 2014 +0200
@@ -22,16 +22,19 @@
  */
 package com.oracle.graal.nodes;
 
-import com.oracle.graal.nodes.type.*;
+import com.oracle.graal.compiler.common.type.*;
+import com.oracle.graal.graph.*;
 
 /**
- * Base class for {@link AbstractBeginNode}s that are associated with a frame state.
- * 
- * TODO (dnsimon) this not needed until {@link AbstractBeginNode} no longer implements
- * {@link StateSplit} which is not possible until loop peeling works without requiring begin nodes
- * to have frames states.
+ * Base class for {@link BeginNode}s that are associated with a frame state.
+ *
+ * TODO (dnsimon) this not needed until {@link BeginNode} no longer implements {@link StateSplit}
+ * which is not possible until loop peeling works without requiring begin nodes to have frames
+ * states.
  */
-public abstract class BeginStateSplitNode extends AbstractBeginNode implements StateSplit {
+public abstract class BeginStateSplitNode extends BeginNode implements StateSplit {
+
+    @Input(InputType.State) private FrameState stateAfter;
 
     public BeginStateSplitNode() {
     }
@@ -40,6 +43,16 @@
         super(stamp);
     }
 
+    public FrameState stateAfter() {
+        return stateAfter;
+    }
+
+    public void setStateAfter(FrameState x) {
+        assert x == null || x.isAlive() : "frame state must be in a graph";
+        updateUsages(stateAfter, x);
+        stateAfter = x;
+    }
+
     /**
      * A begin node has no side effect.
      */
diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/BinaryOpLogicNode.java
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/BinaryOpLogicNode.java	Mon Apr 28 11:18:15 2014 +0200
@@ -0,0 +1,88 @@
+/*
+ * Copyright (c) 2011, 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.graal.nodes;
+
+import com.oracle.graal.api.meta.*;
+import com.oracle.graal.api.meta.ProfilingInfo.*;
+import com.oracle.graal.graph.*;
+import com.oracle.graal.graph.spi.*;
+import com.oracle.graal.nodes.extended.*;
+import com.oracle.graal.nodes.spi.*;
+
+public abstract class BinaryOpLogicNode extends LogicNode implements LIRLowerable, MemoryArithmeticLIRLowerable, Canonicalizable {
+
+    @Input private ValueNode x;
+    @Input private ValueNode y;
+
+    public ValueNode x() {
+        return x;
+    }
+
+    public ValueNode y() {
+        return y;
+    }
+
+    protected void setX(ValueNode x) {
+        updateUsages(this.x, x);
+        this.x = x;
+    }
+
+    protected void setY(ValueNode y) {
+        updateUsages(this.y, y);
+        this.y = y;
+    }
+
+    public BinaryOpLogicNode(ValueNode x, ValueNode y) {
+        assert x != null && y != null && x.getKind() == y.getKind();
+        this.x = x;
+        this.y = y;
+    }
+
+    public abstract TriState evaluate(ConstantReflectionProvider constantReflection, ValueNode forX, ValueNode forY);
+
+    @Override
+    public boolean verify() {
+        assertTrue(x.stamp().isCompatible(y.stamp()), "stamps not compatible: %s, %s", x.stamp(), y.stamp());
+        return super.verify();
+    }
+
+    @Override
+    public Node canonical(CanonicalizerTool tool) {
+        switch (evaluate(tool.getConstantReflection(), x(), y())) {
+            case FALSE:
+                return LogicConstantNode.contradiction(graph());
+            case TRUE:
+                return LogicConstantNode.tautology(graph());
+        }
+        return this;
+    }
+
+    @Override
+    public void generate(NodeLIRBuilderTool gen) {
+    }
+
+    @Override
+    public boolean generate(MemoryArithmeticLIRLowerer gen, Access access) {
+        return false;
+    }
+}
diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/BreakpointNode.java
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/BreakpointNode.java	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/BreakpointNode.java	Mon Apr 28 11:18:15 2014 +0200
@@ -22,9 +22,9 @@
  */
 package com.oracle.graal.nodes;
 
+import com.oracle.graal.compiler.common.type.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.nodes.spi.*;
-import com.oracle.graal.nodes.type.*;
 
 /**
  * A node that results in a platform dependent breakpoint instruction being emitted. A number of
diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/CallTargetNode.java
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/CallTargetNode.java	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/CallTargetNode.java	Mon Apr 28 11:18:15 2014 +0200
@@ -24,9 +24,9 @@
 
 import java.util.*;
 
+import com.oracle.graal.compiler.common.type.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.nodes.spi.*;
-import com.oracle.graal.nodes.type.*;
 
 @NodeInfo(allowedUsageTypes = {InputType.Extension})
 public abstract class CallTargetNode extends ValueNode implements LIRLowerable {
diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/ConditionAnchorNode.java
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/ConditionAnchorNode.java	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/ConditionAnchorNode.java	Mon Apr 28 11:18:15 2014 +0200
@@ -22,11 +22,11 @@
  */
 package com.oracle.graal.nodes;
 
+import com.oracle.graal.compiler.common.type.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.graph.spi.*;
 import com.oracle.graal.nodes.extended.*;
 import com.oracle.graal.nodes.spi.*;
-import com.oracle.graal.nodes.type.*;
 
 @NodeInfo(nameTemplate = "ConditionAnchor(!={p#negated})", allowedUsageTypes = {InputType.Guard})
 public final class ConditionAnchorNode extends FixedWithNextNode implements Canonicalizable, Lowerable, GuardingNode {
diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/ConstantNode.java
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/ConstantNode.java	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/ConstantNode.java	Mon Apr 28 11:18:15 2014 +0200
@@ -25,12 +25,13 @@
 import java.util.*;
 
 import com.oracle.graal.api.meta.*;
+import com.oracle.graal.compiler.common.*;
+import com.oracle.graal.compiler.common.type.*;
 import com.oracle.graal.debug.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.graph.iterators.*;
 import com.oracle.graal.nodes.calc.*;
 import com.oracle.graal.nodes.spi.*;
-import com.oracle.graal.nodes.type.*;
 
 /**
  * The {@code ConstantNode} represents a {@link Constant constant}.
@@ -175,7 +176,8 @@
     public static ConstantNode forPrimitive(Stamp stamp, Constant constant, StructuredGraph graph) {
         if (stamp instanceof IntegerStamp) {
             assert constant.getKind().isNumericInteger() && stamp.getStackKind() == constant.getKind().getStackKind();
-            return forIntegerStamp(stamp, constant.asLong(), graph);
+            IntegerStamp istamp = (IntegerStamp) stamp;
+            return forIntegerBits(istamp.getBits(), constant, graph);
         } else {
             assert constant.getKind().isNumericFloat() && stamp.getStackKind() == constant.getKind();
             return forPrimitive(constant, graph);
@@ -266,19 +268,18 @@
         return graph.unique(node);
     }
 
+    private static ConstantNode forIntegerBits(int bits, Constant constant, StructuredGraph graph) {
+        long value = constant.asLong();
+        long bounds = SignExtendNode.signExtend(value, bits);
+        return unique(graph, new ConstantNode(constant, StampFactory.forInteger(bits, bounds, bounds)));
+    }
+
     /**
      * Returns a node for a constant integer that's not directly representable as Java primitive
      * (e.g. short).
      */
-    public static ConstantNode forIntegerBits(int bits, boolean unsigned, long value, StructuredGraph graph) {
-        Constant constant = Constant.forPrimitiveInt(bits, value);
-        long bounds;
-        if (unsigned) {
-            bounds = ZeroExtendNode.zeroExtend(value, bits);
-        } else {
-            bounds = SignExtendNode.signExtend(value, bits);
-        }
-        return unique(graph, new ConstantNode(constant, StampFactory.forInteger(bits, unsigned, bounds, bounds)));
+    public static ConstantNode forIntegerBits(int bits, long value, StructuredGraph graph) {
+        return forIntegerBits(bits, Constant.forPrimitiveInt(bits, value), graph);
     }
 
     /**
@@ -287,7 +288,7 @@
     public static ConstantNode forIntegerStamp(Stamp stamp, long value, StructuredGraph graph) {
         if (stamp instanceof IntegerStamp) {
             IntegerStamp intStamp = (IntegerStamp) stamp;
-            return forIntegerBits(intStamp.getBits(), intStamp.isUnsigned(), value, graph);
+            return forIntegerBits(intStamp.getBits(), value, graph);
         } else {
             return forIntegerKind(stamp.getStackKind(), value, graph);
         }
diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/ControlSinkNode.java
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/ControlSinkNode.java	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/ControlSinkNode.java	Mon Apr 28 11:18:15 2014 +0200
@@ -22,7 +22,7 @@
  */
 package com.oracle.graal.nodes;
 
-import com.oracle.graal.nodes.type.*;
+import com.oracle.graal.compiler.common.type.*;
 
 public abstract class ControlSinkNode extends FixedNode {
 
diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/ControlSplitNode.java
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/ControlSplitNode.java	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/ControlSplitNode.java	Mon Apr 28 11:18:15 2014 +0200
@@ -22,8 +22,8 @@
  */
 package com.oracle.graal.nodes;
 
+import com.oracle.graal.compiler.common.type.*;
 import com.oracle.graal.graph.*;
-import com.oracle.graal.nodes.type.*;
 
 /**
  * The {@code ControlSplitNode} is a base class for all instructions that split the control flow
@@ -35,7 +35,7 @@
         super(stamp);
     }
 
-    public abstract double probability(AbstractBeginNode successor);
+    public abstract double probability(BeginNode successor);
 
-    public abstract void setProbability(AbstractBeginNode successor, double value);
+    public abstract void setProbability(BeginNode successor, double value);
 }
diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/DeoptimizeNode.java
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/DeoptimizeNode.java	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/DeoptimizeNode.java	Mon Apr 28 11:18:15 2014 +0200
@@ -63,7 +63,7 @@
 
     @Override
     public void generate(NodeLIRBuilderTool gen) {
-        gen.getLIRGeneratorTool().emitDeoptimize(gen.getLIRGeneratorTool().getMetaAccess().encodeDeoptActionAndReason(action, reason, debugId), speculation, this);
+        gen.getLIRGeneratorTool().emitDeoptimize(gen.getLIRGeneratorTool().getMetaAccess().encodeDeoptActionAndReason(action, reason, debugId), speculation, gen.state(this));
     }
 
     @Override
diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/DeoptimizingFixedWithNextNode.java
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/DeoptimizingFixedWithNextNode.java	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/DeoptimizingFixedWithNextNode.java	Mon Apr 28 11:18:15 2014 +0200
@@ -22,8 +22,8 @@
  */
 package com.oracle.graal.nodes;
 
+import com.oracle.graal.compiler.common.type.*;
 import com.oracle.graal.graph.*;
-import com.oracle.graal.nodes.type.*;
 
 public abstract class DeoptimizingFixedWithNextNode extends FixedWithNextNode implements DeoptimizingNode.DeoptBefore {
 
diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/DirectCallTargetNode.java
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/DirectCallTargetNode.java	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/DirectCallTargetNode.java	Mon Apr 28 11:18:15 2014 +0200
@@ -26,7 +26,7 @@
 
 import com.oracle.graal.api.code.*;
 import com.oracle.graal.api.meta.*;
-import com.oracle.graal.nodes.type.*;
+import com.oracle.graal.compiler.common.type.*;
 
 public class DirectCallTargetNode extends LoweredCallTargetNode {
 
diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/DispatchBeginNode.java
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/DispatchBeginNode.java	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/DispatchBeginNode.java	Mon Apr 28 11:18:15 2014 +0200
@@ -22,7 +22,7 @@
  */
 package com.oracle.graal.nodes;
 
-import com.oracle.graal.nodes.type.*;
+import com.oracle.graal.compiler.common.type.*;
 
 /**
  * The entry node of an exception dispatcher block.
diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/DynamicDeoptimizeNode.java
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/DynamicDeoptimizeNode.java	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/DynamicDeoptimizeNode.java	Mon Apr 28 11:18:15 2014 +0200
@@ -55,7 +55,7 @@
     }
 
     public void generate(NodeLIRBuilderTool generator) {
-        generator.getLIRGeneratorTool().emitDeoptimize(generator.operand(actionAndReason), generator.operand(speculation), this);
+        generator.getLIRGeneratorTool().emitDeoptimize(generator.operand(actionAndReason), generator.operand(speculation), generator.state(this));
     }
 
     @Override
diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/EntryMarkerNode.java
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/EntryMarkerNode.java	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/EntryMarkerNode.java	Mon Apr 28 11:18:15 2014 +0200
@@ -22,6 +22,7 @@
  */
 package com.oracle.graal.nodes;
 
+import com.oracle.graal.compiler.common.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.graph.spi.*;
 import com.oracle.graal.nodes.spi.*;
@@ -31,7 +32,7 @@
  * by the graph builder.
  */
 @NodeInfo(allowedUsageTypes = {InputType.Association})
-public class EntryMarkerNode extends AbstractBeginNode implements IterableNodeType, Simplifiable, LIRLowerable {
+public class EntryMarkerNode extends BeginStateSplitNode implements IterableNodeType, Simplifiable, LIRLowerable {
 
     @Override
     public void simplify(SimplifierTool tool) {
diff -r 3dde8d8c95b8 -r 40d0022115ee 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	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/FixedNode.java	Mon Apr 28 11:18:15 2014 +0200
@@ -22,7 +22,7 @@
  */
 package com.oracle.graal.nodes;
 
-import com.oracle.graal.nodes.type.*;
+import com.oracle.graal.compiler.common.type.*;
 
 public abstract class FixedNode extends ValueNode {
 
diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/FixedWithNextNode.java
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/FixedWithNextNode.java	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/FixedWithNextNode.java	Mon Apr 28 11:18:15 2014 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2009, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2009, 2014, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -22,7 +22,7 @@
  */
 package com.oracle.graal.nodes;
 
-import com.oracle.graal.nodes.type.*;
+import com.oracle.graal.compiler.common.type.*;
 
 /**
  * Base class of all nodes that are fixed within the control flow graph and have an immediate
@@ -44,4 +44,9 @@
     public FixedWithNextNode(Stamp stamp) {
         super(stamp);
     }
+
+    @Override
+    public FixedWithNextNode asNode() {
+        return this;
+    }
 }
diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/FloatingAnchoredNode.java
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/FloatingAnchoredNode.java	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/FloatingAnchoredNode.java	Mon Apr 28 11:18:15 2014 +0200
@@ -22,10 +22,10 @@
  */
 package com.oracle.graal.nodes;
 
+import com.oracle.graal.compiler.common.type.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.nodes.calc.*;
 import com.oracle.graal.nodes.extended.*;
-import com.oracle.graal.nodes.type.*;
 
 public abstract class FloatingAnchoredNode extends FloatingNode {
 
diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/FloatingGuardedNode.java
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/FloatingGuardedNode.java	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/FloatingGuardedNode.java	Mon Apr 28 11:18:15 2014 +0200
@@ -22,10 +22,10 @@
  */
 package com.oracle.graal.nodes;
 
+import com.oracle.graal.compiler.common.type.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.nodes.calc.*;
 import com.oracle.graal.nodes.extended.*;
-import com.oracle.graal.nodes.type.*;
 
 public abstract class FloatingGuardedNode extends FloatingNode implements GuardedNode {
 
diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/FrameState.java
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/FrameState.java	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/FrameState.java	Mon Apr 28 11:18:15 2014 +0200
@@ -51,35 +51,6 @@
 
     private boolean duringCall;
 
-    /**
-     * This BCI should be used for frame states that are built for code with no meaningful BCI.
-     */
-    public static final int UNKNOWN_BCI = -4;
-
-    /**
-     * When a node whose frame state has this BCI value is inlined, its frame state will be replaced
-     * with the frame state before the inlined invoke node.
-     */
-    public static final int BEFORE_BCI = -1;
-
-    /**
-     * When a node whose frame state has this BCI value is inlined, its frame state will be replaced
-     * with the frame state {@linkplain Invoke#stateAfter() after} the inlined invoke node.
-     */
-    public static final int AFTER_BCI = -2;
-
-    /**
-     * When a node whose frame state has this BCI value is inlined, its frame state will be replaced
-     * with the frame state at the exception edge of the inlined invoke node.
-     */
-    public static final int AFTER_EXCEPTION_BCI = -3;
-
-    /**
-     * This BCI should be used for frame states that cannot be the target of a deoptimization, like
-     * snippet frame states.
-     */
-    public static final int INVALID_FRAMESTATE_BCI = -5;
-
     @Input(InputType.State) private FrameState outerFrameState;
 
     /**
@@ -124,8 +95,8 @@
         this.virtualObjectMappings = new NodeInputList<>(this, virtualObjectMappings);
         this.rethrowException = rethrowException;
         this.duringCall = duringCall;
-        assert !rethrowException || stackSize == 1 : "must have exception on top of the stack";
-        assert values.size() - localsSize - stackSize == monitorIds.size();
+        assert !this.rethrowException || this.stackSize == 1 : "must have exception on top of the stack";
+        assert this.locksSize() == this.monitorIds.size();
     }
 
     /**
@@ -135,7 +106,8 @@
      */
     public FrameState(int bci) {
         this(null, bci, Collections. emptyList(), 0, 0, false, false, Collections. emptyList(), Collections. emptyList());
-        assert bci == BEFORE_BCI || bci == AFTER_BCI || bci == AFTER_EXCEPTION_BCI || bci == UNKNOWN_BCI || bci == INVALID_FRAMESTATE_BCI;
+        assert bci == BytecodeFrame.BEFORE_BCI || bci == BytecodeFrame.AFTER_BCI || bci == BytecodeFrame.AFTER_EXCEPTION_BCI || bci == BytecodeFrame.UNKNOWN_BCI ||
+                        bci == BytecodeFrame.INVALID_FRAMESTATE_BCI;
     }
 
     public FrameState(ResolvedJavaMethod method, int bci, ValueNode[] locals, List stack, ValueNode[] locks, MonitorIdNode[] monitorIds, boolean rethrowException, boolean duringCall) {
@@ -248,6 +220,19 @@
      * correctly in slot encoding: a long or double will be followed by a null slot.
      */
     public FrameState duplicateModified(int newBci, boolean newRethrowException, Kind popKind, ValueNode... pushedValues) {
+        return duplicateModified(newBci, method, newRethrowException, popKind, pushedValues);
+    }
+
+    /**
+     * Creates a copy of this frame state with one stack element of type popKind popped from the
+     * stack and the values in pushedValues pushed on the stack. The pushedValues will be formatted
+     * correctly in slot encoding: a long or double will be followed by a null slot.
+     */
+    public FrameState duplicateModified(Kind popKind, ValueNode... pushedValues) {
+        return duplicateModified(bci, method, rethrowException, popKind, pushedValues);
+    }
+
+    private FrameState duplicateModified(int newBci, ResolvedJavaMethod newMethod, boolean newRethrowException, Kind popKind, ValueNode... pushedValues) {
         ArrayList copy = new ArrayList<>(values.subList(0, localsSize + stackSize));
         if (popKind != Kind.Void) {
             if (stackAt(stackSize() - 1) == null) {
@@ -266,7 +251,7 @@
         int newStackSize = copy.size() - localsSize;
         copy.addAll(values.subList(localsSize + stackSize, values.size()));
 
-        FrameState other = graph().add(new FrameState(method, newBci, copy, localsSize, newStackSize, newRethrowException, false, monitorIds, virtualObjectMappings));
+        FrameState other = graph().add(new FrameState(newMethod, newBci, copy, localsSize, newStackSize, newRethrowException, false, monitorIds, virtualObjectMappings));
         other.setOuterFrameState(outerFrameState());
         return other;
     }
@@ -395,13 +380,26 @@
                 properties.put("sourceLine", ste.getLineNumber());
             }
         }
+        if (bci == BytecodeFrame.AFTER_BCI) {
+            properties.put("bci", "AFTER_BCI");
+        } else if (bci == BytecodeFrame.AFTER_EXCEPTION_BCI) {
+            properties.put("bci", "AFTER_EXCEPTION_BCI");
+        } else if (bci == BytecodeFrame.INVALID_FRAMESTATE_BCI) {
+            properties.put("bci", "INVALID_FRAMESTATE_BCI");
+        } else if (bci == BytecodeFrame.BEFORE_BCI) {
+            properties.put("bci", "BEFORE_BCI");
+        } else if (bci == BytecodeFrame.UNKNOWN_BCI) {
+            properties.put("bci", "UNKNOWN_BCI");
+        } else if (bci == BytecodeFrame.UNWIND_BCI) {
+            properties.put("bci", "UNWIND_BCI");
+        }
         properties.put("locksSize", values.size() - stackSize - localsSize);
         return properties;
     }
 
     @Override
     public boolean verify() {
-        assertTrue(values.size() - localsSize - stackSize == monitorIds.size(), "mismatch in number of locks");
+        assertTrue(locksSize() == monitorIds.size(), "mismatch in number of locks");
         for (ValueNode value : values) {
             assertTrue(value == null || !value.isDeleted(), "frame state must not contain deleted nodes");
             assertTrue(value == null || value instanceof VirtualObjectNode || (value.getKind() != Kind.Void), "unexpected value: %s", value);
diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/GuardNode.java
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/GuardNode.java	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/GuardNode.java	Mon Apr 28 11:18:15 2014 +0200
@@ -23,10 +23,10 @@
 package com.oracle.graal.nodes;
 
 import com.oracle.graal.api.meta.*;
+import com.oracle.graal.compiler.common.type.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.graph.spi.*;
 import com.oracle.graal.nodes.extended.*;
-import com.oracle.graal.nodes.type.*;
 
 /**
  * A guard is a node that deoptimizes based on a conditional expression. Guards are not attached to
@@ -107,7 +107,8 @@
         } else if (condition() instanceof LogicConstantNode) {
             LogicConstantNode c = (LogicConstantNode) condition();
             if (c.getValue() != negated) {
-                return graph().start();
+                this.replaceAtUsages(null);
+                return null;
             }
         }
         return this;
diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/GuardPhiNode.java
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/GuardPhiNode.java	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/GuardPhiNode.java	Mon Apr 28 11:18:15 2014 +0200
@@ -22,9 +22,9 @@
  */
 package com.oracle.graal.nodes;
 
+import com.oracle.graal.compiler.common.type.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.nodes.extended.*;
-import com.oracle.graal.nodes.type.*;
 
 @NodeInfo(nameTemplate = "GuardPhi({i#values})", allowedUsageTypes = {InputType.Guard})
 public class GuardPhiNode extends PhiNode implements GuardingNode {
diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/GuardProxyNode.java
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/GuardProxyNode.java	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/GuardProxyNode.java	Mon Apr 28 11:18:15 2014 +0200
@@ -22,22 +22,26 @@
  */
 package com.oracle.graal.nodes;
 
+import com.oracle.graal.compiler.common.type.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.nodes.extended.*;
 import com.oracle.graal.nodes.spi.*;
-import com.oracle.graal.nodes.type.*;
 
 @NodeInfo(allowedUsageTypes = {InputType.Guard})
-public class GuardProxyNode extends ProxyNode implements GuardingNode, Proxy {
+public class GuardProxyNode extends ProxyNode implements GuardingNode, Proxy, LIRLowerable {
 
     @Input(InputType.Guard) private GuardingNode value;
 
-    public GuardProxyNode(GuardingNode value, AbstractBeginNode proxyPoint) {
+    public GuardProxyNode(GuardingNode value, BeginNode proxyPoint) {
         super(StampFactory.forVoid(), proxyPoint);
         this.value = value;
     }
 
     @Override
+    public void generate(NodeLIRBuilderTool generator) {
+    }
+
+    @Override
     public ValueNode value() {
         return value.asNode();
     }
diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/GuardedValueNode.java
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/GuardedValueNode.java	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/GuardedValueNode.java	Mon Apr 28 11:18:15 2014 +0200
@@ -23,11 +23,11 @@
 package com.oracle.graal.nodes;
 
 import com.oracle.graal.api.meta.*;
+import com.oracle.graal.compiler.common.type.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.graph.spi.*;
 import com.oracle.graal.nodes.extended.*;
 import com.oracle.graal.nodes.spi.*;
-import com.oracle.graal.nodes.type.*;
 
 /**
  * A node that changes the type of its input, usually narrowing it. For example, a GuardedValueNode
@@ -77,7 +77,7 @@
 
     @Override
     public Node canonical(CanonicalizerTool tool) {
-        if (getGuard() == graph().start()) {
+        if (getGuard() == null) {
             if (stamp().equals(object().stamp())) {
                 return object();
             } else {
diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/GuardingPiNode.java
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/GuardingPiNode.java	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/GuardingPiNode.java	Mon Apr 28 11:18:15 2014 +0200
@@ -23,6 +23,7 @@
 package com.oracle.graal.nodes;
 
 import com.oracle.graal.api.meta.*;
+import com.oracle.graal.compiler.common.type.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.graph.spi.*;
 import com.oracle.graal.nodes.calc.*;
@@ -50,6 +51,18 @@
         return condition;
     }
 
+    public boolean isNegated() {
+        return negated;
+    }
+
+    public DeoptimizationReason getReason() {
+        return reason;
+    }
+
+    public DeoptimizationAction getAction() {
+        return action;
+    }
+
     /**
      * Constructor for {@link #guardingNonNull(Object)} node intrinsic.
      */
@@ -87,7 +100,7 @@
     @Override
     public void virtualize(VirtualizerTool tool) {
         State state = tool.getObjectState(object);
-        if (state != null && state.getState() == EscapeState.Virtual && ObjectStamp.typeOrNull(this) != null && ObjectStamp.typeOrNull(this).isAssignableFrom(state.getVirtualObject().type())) {
+        if (state != null && state.getState() == EscapeState.Virtual && StampTool.typeOrNull(this) != null && StampTool.typeOrNull(this).isAssignableFrom(state.getVirtualObject().type())) {
             tool.replaceWithVirtual(state.getVirtualObject());
         }
     }
diff -r 3dde8d8c95b8 -r 40d0022115ee 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	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/IfNode.java	Mon Apr 28 11:18:15 2014 +0200
@@ -27,6 +27,8 @@
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.api.meta.JavaTypeProfile.ProfiledType;
 import com.oracle.graal.api.meta.ProfilingInfo.TriState;
+import com.oracle.graal.compiler.common.calc.*;
+import com.oracle.graal.compiler.common.type.*;
 import com.oracle.graal.debug.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.graph.iterators.*;
@@ -35,7 +37,6 @@
 import com.oracle.graal.nodes.extended.*;
 import com.oracle.graal.nodes.java.*;
 import com.oracle.graal.nodes.spi.*;
-import com.oracle.graal.nodes.type.*;
 import com.oracle.graal.nodes.util.*;
 
 /**
@@ -44,8 +45,8 @@
  */
 public final class IfNode extends ControlSplitNode implements Simplifiable, LIRLowerable, MemoryArithmeticLIRLowerable {
 
-    @Successor private AbstractBeginNode trueSuccessor;
-    @Successor private AbstractBeginNode falseSuccessor;
+    @Successor private BeginNode trueSuccessor;
+    @Successor private BeginNode falseSuccessor;
     @Input(InputType.Condition) private LogicNode condition;
     private double trueSuccessorProbability;
 
@@ -59,10 +60,10 @@
     }
 
     public IfNode(LogicNode condition, FixedNode trueSuccessor, FixedNode falseSuccessor, double trueSuccessorProbability) {
-        this(condition, AbstractBeginNode.begin(trueSuccessor), AbstractBeginNode.begin(falseSuccessor), trueSuccessorProbability);
+        this(condition, BeginNode.begin(trueSuccessor), BeginNode.begin(falseSuccessor), trueSuccessorProbability);
     }
 
-    public IfNode(LogicNode condition, AbstractBeginNode trueSuccessor, AbstractBeginNode falseSuccessor, double trueSuccessorProbability) {
+    public IfNode(LogicNode condition, BeginNode trueSuccessor, BeginNode falseSuccessor, double trueSuccessorProbability) {
         super(StampFactory.forVoid());
         this.condition = condition;
         this.falseSuccessor = falseSuccessor;
@@ -76,7 +77,7 @@
      *
      * @return the true successor
      */
-    public AbstractBeginNode trueSuccessor() {
+    public BeginNode trueSuccessor() {
         return trueSuccessor;
     }
 
@@ -85,16 +86,16 @@
      *
      * @return the false successor
      */
-    public AbstractBeginNode falseSuccessor() {
+    public BeginNode falseSuccessor() {
         return falseSuccessor;
     }
 
-    public void setTrueSuccessor(AbstractBeginNode node) {
+    public void setTrueSuccessor(BeginNode node) {
         updatePredecessor(trueSuccessor, node);
         trueSuccessor = node;
     }
 
-    public void setFalseSuccessor(AbstractBeginNode node) {
+    public void setFalseSuccessor(BeginNode node) {
         updatePredecessor(falseSuccessor, node);
         falseSuccessor = node;
     }
@@ -105,7 +106,7 @@
      * @param istrue {@code true} if the true successor is requested, {@code false} otherwise
      * @return the corresponding successor
      */
-    public AbstractBeginNode successor(boolean istrue) {
+    public BeginNode successor(boolean istrue) {
         return istrue ? trueSuccessor : falseSuccessor;
     }
 
@@ -115,12 +116,12 @@
     }
 
     @Override
-    public double probability(AbstractBeginNode successor) {
+    public double probability(BeginNode successor) {
         return successor == trueSuccessor ? trueSuccessorProbability : 1 - trueSuccessorProbability;
     }
 
     @Override
-    public void setProbability(AbstractBeginNode successor, double value) {
+    public void setProbability(BeginNode successor, double value) {
         assert successor == trueSuccessor || successor == falseSuccessor;
         setTrueSuccessorProbability(successor == trueSuccessor ? value : 1 - value);
     }
@@ -146,8 +147,8 @@
     @Override
     public void simplify(SimplifierTool tool) {
         if (condition() instanceof LogicNegationNode) {
-            AbstractBeginNode trueSucc = trueSuccessor();
-            AbstractBeginNode falseSucc = falseSuccessor();
+            BeginNode trueSucc = trueSuccessor();
+            BeginNode falseSucc = falseSuccessor();
             setTrueSuccessor(null);
             setFalseSuccessor(null);
             LogicNegationNode negation = (LogicNegationNode) condition();
@@ -156,6 +157,41 @@
             this.safeDelete();
             return;
         }
+        if (trueSuccessor().usages().isEmpty() && falseSuccessor().usages().isEmpty()) {
+            // push similar nodes upwards through the if, thereby deduplicating them
+            do {
+                BeginNode trueSucc = trueSuccessor();
+                BeginNode falseSucc = falseSuccessor();
+                if (trueSucc.getClass() == BeginNode.class && falseSucc.getClass() == BeginNode.class && trueSucc.next() instanceof FixedWithNextNode && falseSucc.next() instanceof FixedWithNextNode) {
+                    FixedWithNextNode trueNext = (FixedWithNextNode) trueSucc.next();
+                    FixedWithNextNode falseNext = (FixedWithNextNode) falseSucc.next();
+                    NodeClass nodeClass = trueNext.getNodeClass();
+                    if (trueNext.getClass() == falseNext.getClass()) {
+                        if (nodeClass.inputsEqual(trueNext, falseNext) && nodeClass.valueEqual(trueNext, falseNext)) {
+                            falseNext.replaceAtUsages(trueNext);
+                            graph().removeFixed(falseNext);
+                            FixedNode next = trueNext.next();
+                            trueNext.setNext(null);
+                            trueNext.replaceAtPredecessor(next);
+                            graph().addBeforeFixed(this, trueNext);
+                            for (Node usage : trueNext.usages().snapshot()) {
+                                if (usage.getNodeClass().valueNumberable() && !usage.getNodeClass().isLeafNode()) {
+                                    Node newNode = graph().findDuplicate(usage);
+                                    if (newNode != null) {
+                                        usage.replaceAtUsages(newNode);
+                                        usage.safeDelete();
+                                    }
+                                }
+                                if (usage.isAlive()) {
+                                    tool.addToWorkList(usage);
+                                }
+                            }
+                            continue;
+                        }
+                    }
+                }
+            } while (false);
+        }
 
         if (condition() instanceof LogicConstantNode) {
             LogicConstantNode c = (LogicConstantNode) condition();
@@ -182,7 +218,7 @@
         }
 
         if (falseSuccessor().usages().isEmpty() && (!(falseSuccessor() instanceof LoopExitNode)) && falseSuccessor().next() instanceof IfNode) {
-            AbstractBeginNode intermediateBegin = falseSuccessor();
+            BeginNode intermediateBegin = falseSuccessor();
             IfNode nextIf = (IfNode) intermediateBegin.next();
             double probabilityB = (1.0 - this.trueSuccessorProbability) * nextIf.trueSuccessorProbability;
             if (this.trueSuccessorProbability < probabilityB) {
@@ -191,7 +227,7 @@
                 if (prepareForSwap(tool.getConstantReflection(), condition(), nextIf.condition(), this.trueSuccessorProbability, probabilityB)) {
                     // Reording is allowed from (if1 => begin => if2) to (if2 => begin => if1).
                     assert intermediateBegin.next() == nextIf;
-                    AbstractBeginNode bothFalseBegin = nextIf.falseSuccessor();
+                    BeginNode bothFalseBegin = nextIf.falseSuccessor();
                     nextIf.setFalseSuccessor(null);
                     intermediateBegin.setNext(null);
                     this.setFalseSuccessor(null);
@@ -547,8 +583,8 @@
         List trueEnds = new ArrayList<>(mergePredecessors.size());
         Map phiValues = new HashMap<>(mergePredecessors.size());
 
-        AbstractBeginNode oldFalseSuccessor = falseSuccessor();
-        AbstractBeginNode oldTrueSuccessor = trueSuccessor();
+        BeginNode oldFalseSuccessor = falseSuccessor();
+        BeginNode oldTrueSuccessor = trueSuccessor();
 
         setFalseSuccessor(null);
         setTrueSuccessor(null);
@@ -637,7 +673,7 @@
      * @param oldMerge the merge being removed
      * @param phiValues the values of the phi at the merge, keyed by the merge ends
      */
-    private void connectEnds(List ends, Map phiValues, AbstractBeginNode successor, MergeNode oldMerge, SimplifierTool tool) {
+    private void connectEnds(List ends, Map phiValues, BeginNode successor, MergeNode oldMerge, SimplifierTool tool) {
         if (!ends.isEmpty()) {
             if (ends.size() == 1) {
                 AbstractEndNode end = ends.get(0);
@@ -703,8 +739,8 @@
     }
 
     private void removeEmptyIf(SimplifierTool tool) {
-        AbstractBeginNode originalTrueSuccessor = trueSuccessor();
-        AbstractBeginNode originalFalseSuccessor = falseSuccessor();
+        BeginNode originalTrueSuccessor = trueSuccessor();
+        BeginNode originalFalseSuccessor = falseSuccessor();
         assert originalTrueSuccessor.next() instanceof AbstractEndNode && originalFalseSuccessor.next() instanceof AbstractEndNode;
 
         AbstractEndNode trueEnd = (AbstractEndNode) originalTrueSuccessor.next();
diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/IndirectCallTargetNode.java
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/IndirectCallTargetNode.java	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/IndirectCallTargetNode.java	Mon Apr 28 11:18:15 2014 +0200
@@ -26,7 +26,7 @@
 
 import com.oracle.graal.api.code.*;
 import com.oracle.graal.api.meta.*;
-import com.oracle.graal.nodes.type.*;
+import com.oracle.graal.compiler.common.type.*;
 
 public class IndirectCallTargetNode extends LoweredCallTargetNode {
 
@@ -43,6 +43,6 @@
 
     @Override
     public String targetName() {
-        return "Indirect#" + ((JavaMethod) target()).getName();
+        return MetaUtil.format("Indirect#%h.%n", target());
     }
 }
diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/InfopointNode.java
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/InfopointNode.java	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/InfopointNode.java	Mon Apr 28 11:18:15 2014 +0200
@@ -23,9 +23,9 @@
 package com.oracle.graal.nodes;
 
 import com.oracle.graal.api.code.*;
+import com.oracle.graal.compiler.common.type.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.nodes.spi.*;
-import com.oracle.graal.nodes.type.*;
 
 /**
  * Nodes of this type are inserted into the graph to denote points of interest to debugging.
diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/Invoke.java
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/Invoke.java	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/Invoke.java	Mon Apr 28 11:18:15 2014 +0200
@@ -22,6 +22,7 @@
  */
 package com.oracle.graal.nodes;
 
+import com.oracle.graal.api.meta.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.nodes.extended.*;
 import com.oracle.graal.nodes.spi.*;
@@ -52,4 +53,36 @@
     boolean isPolymorphic();
 
     void setPolymorphic(boolean value);
+
+    /**
+     * Returns the {@linkplain ResolvedJavaMethod method} from which this invoke is executed. This
+     * is the caller method and in the case of inlining may be different from the method of the
+     * graph this node is in.
+     *
+     * @return the method from which this invoke is executed.
+     */
+    default ResolvedJavaMethod getContextMethod() {
+        FrameState state = stateAfter();
+        if (state == null) {
+            state = stateDuring();
+        }
+        return state.method();
+    }
+
+    /**
+     * Returns the {@linkplain ResolvedJavaType type} from which this invoke is executed. This is
+     * the declaring type of the caller method.
+     *
+     * @return the type from which this invoke is executed.
+     */
+    default ResolvedJavaType getContextType() {
+        return getContextMethod().getDeclaringClass();
+    }
+
+    @Override
+    default void computeStateDuring(FrameState stateAfter) {
+        FrameState newStateDuring = stateAfter.duplicateModified(bci(), stateAfter.rethrowException(), asNode().getKind());
+        newStateDuring.setDuringCall(true);
+        setStateDuring(newStateDuring);
+    }
 }
diff -r 3dde8d8c95b8 -r 40d0022115ee 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	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/InvokeNode.java	Mon Apr 28 11:18:15 2014 +0200
@@ -25,11 +25,11 @@
 import java.util.*;
 
 import com.oracle.graal.api.meta.*;
+import com.oracle.graal.compiler.common.type.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.nodes.extended.*;
 import com.oracle.graal.nodes.java.*;
 import com.oracle.graal.nodes.spi.*;
-import com.oracle.graal.nodes.type.*;
 import com.oracle.graal.nodes.util.*;
 
 /**
@@ -185,13 +185,6 @@
     }
 
     @Override
-    public void computeStateDuring(FrameState stateAfter) {
-        FrameState newStateDuring = stateAfter.duplicateModified(bci(), stateAfter.rethrowException(), getKind());
-        newStateDuring.setDuringCall(true);
-        setStateDuring(newStateDuring);
-    }
-
-    @Override
     public GuardingNode getGuard() {
         return guard;
     }
diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/InvokeWithExceptionNode.java
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/InvokeWithExceptionNode.java	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/InvokeWithExceptionNode.java	Mon Apr 28 11:18:15 2014 +0200
@@ -36,8 +36,8 @@
 
     private static final double EXCEPTION_PROBA = 1e-5;
 
-    @Successor private AbstractBeginNode next;
-    @Successor private DispatchBeginNode exceptionEdge;
+    @Successor private BeginNode next;
+    @Successor private BeginNode exceptionEdge;
     @Input(InputType.Extension) private CallTargetNode callTarget;
     @Input(InputType.State) private FrameState stateDuring;
     @Input(InputType.State) private FrameState stateAfter;
@@ -47,7 +47,7 @@
     private boolean useForInlining;
     private double exceptionProbability;
 
-    public InvokeWithExceptionNode(CallTargetNode callTarget, DispatchBeginNode exceptionEdge, int bci) {
+    public InvokeWithExceptionNode(CallTargetNode callTarget, BeginNode exceptionEdge, int bci) {
         super(callTarget.returnStamp());
         this.exceptionEdge = exceptionEdge;
         this.bci = bci;
@@ -57,20 +57,20 @@
         this.exceptionProbability = EXCEPTION_PROBA;
     }
 
-    public DispatchBeginNode exceptionEdge() {
+    public BeginNode exceptionEdge() {
         return exceptionEdge;
     }
 
-    public void setExceptionEdge(DispatchBeginNode x) {
+    public void setExceptionEdge(BeginNode x) {
         updatePredecessor(exceptionEdge, x);
         exceptionEdge = x;
     }
 
-    public AbstractBeginNode next() {
+    public BeginNode next() {
         return next;
     }
 
-    public void setNext(AbstractBeginNode x) {
+    public void setNext(BeginNode x) {
         updatePredecessor(next, x);
         next = x;
     }
@@ -163,7 +163,7 @@
     }
 
     public void killExceptionEdge() {
-        AbstractBeginNode edge = exceptionEdge();
+        BeginNode edge = exceptionEdge();
         setExceptionEdge(null);
         GraphUtil.killCFG(edge);
     }
@@ -196,12 +196,12 @@
     }
 
     @Override
-    public double probability(AbstractBeginNode successor) {
+    public double probability(BeginNode successor) {
         return successor == next ? 1 - exceptionProbability : exceptionProbability;
     }
 
     @Override
-    public void setProbability(AbstractBeginNode successor, double value) {
+    public void setProbability(BeginNode successor, double value) {
         assert successor == next || successor == exceptionEdge;
         this.exceptionProbability = successor == next ? 1 - value : value;
     }
@@ -223,13 +223,6 @@
     }
 
     @Override
-    public void computeStateDuring(FrameState tempStateAfter) {
-        FrameState newStateDuring = tempStateAfter.duplicateModified(bci(), tempStateAfter.rethrowException(), getKind());
-        newStateDuring.setDuringCall(true);
-        setStateDuring(newStateDuring);
-    }
-
-    @Override
     public GuardingNode getGuard() {
         return guard;
     }
diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/KillingBeginNode.java
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/KillingBeginNode.java	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/KillingBeginNode.java	Mon Apr 28 11:18:15 2014 +0200
@@ -27,7 +27,7 @@
 import com.oracle.graal.nodes.extended.*;
 
 @NodeInfo(allowedUsageTypes = {InputType.Memory})
-public class KillingBeginNode extends AbstractBeginNode implements MemoryCheckpoint.Single {
+public class KillingBeginNode extends BeginNode implements MemoryCheckpoint.Single {
 
     private LocationIdentity locationIdentity;
 
diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/LogicNode.java
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/LogicNode.java	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/LogicNode.java	Mon Apr 28 11:18:15 2014 +0200
@@ -24,9 +24,9 @@
 
 import static com.oracle.graal.graph.InputType.*;
 
+import com.oracle.graal.compiler.common.type.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.nodes.calc.*;
-import com.oracle.graal.nodes.type.*;
 
 @NodeInfo(allowedUsageTypes = {Condition})
 public abstract class LogicNode extends FloatingNode {
diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/LoopBeginNode.java
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/LoopBeginNode.java	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/LoopBeginNode.java	Mon Apr 28 11:18:15 2014 +0200
@@ -178,7 +178,7 @@
         // nothing yet
     }
 
-    public boolean isLoopExit(AbstractBeginNode begin) {
+    public boolean isLoopExit(BeginNode begin) {
         return begin instanceof LoopExitNode && ((LoopExitNode) begin).loopBegin() == this;
     }
 
@@ -201,4 +201,27 @@
         updateUsagesInterface(this.overflowGuard, overflowGuard);
         this.overflowGuard = overflowGuard;
     }
+
+    /**
+     * Removes dead {@linkplain PhiNode phi nodes} hanging from this node.
+     *
+     * This method uses the heuristic that any node which not a phi node of this LoopBeginNode is
+     * alive. This allows the removal of dead phi loops.
+     */
+    public void removeDeadPhis() {
+        Set alive = new HashSet<>();
+        for (PhiNode phi : phis()) {
+            NodePredicate isAlive = u -> !isPhiAtMerge(u) || alive.contains(u);
+            if (phi.usages().filter(isAlive).isNotEmpty()) {
+                alive.add(phi);
+                for (PhiNode keptAlive : phi.values().filter(PhiNode.class).filter(isAlive.negate())) {
+                    alive.add(keptAlive);
+                }
+            }
+        }
+        for (PhiNode phi : phis().filter(((NodePredicate) alive::contains).negate()).snapshot()) {
+            phi.replaceAtUsages(null);
+            phi.safeDelete();
+        }
+    }
 }
diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/LoweredCallTargetNode.java
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/LoweredCallTargetNode.java	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/LoweredCallTargetNode.java	Mon Apr 28 11:18:15 2014 +0200
@@ -26,7 +26,7 @@
 
 import com.oracle.graal.api.code.*;
 import com.oracle.graal.api.meta.*;
-import com.oracle.graal.nodes.type.*;
+import com.oracle.graal.compiler.common.type.*;
 
 public abstract class LoweredCallTargetNode extends CallTargetNode {
 
diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/MemoryMapNode.java
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/MemoryMapNode.java	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/MemoryMapNode.java	Mon Apr 28 11:18:15 2014 +0200
@@ -25,10 +25,10 @@
 import java.util.*;
 
 import com.oracle.graal.api.meta.*;
+import com.oracle.graal.compiler.common.type.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.nodes.calc.*;
 import com.oracle.graal.nodes.extended.*;
-import com.oracle.graal.nodes.type.*;
 
 @NodeInfo(allowedUsageTypes = {InputType.Extension})
 public abstract class MemoryMapNode extends FloatingNode {
diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/MemoryPhiNode.java
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/MemoryPhiNode.java	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/MemoryPhiNode.java	Mon Apr 28 11:18:15 2014 +0200
@@ -23,9 +23,9 @@
 package com.oracle.graal.nodes;
 
 import com.oracle.graal.api.meta.*;
+import com.oracle.graal.compiler.common.type.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.nodes.extended.*;
-import com.oracle.graal.nodes.type.*;
 
 /**
  * The {@code PhiNode} represents the merging of dataflow in the memory graph.
diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/MemoryProxyNode.java
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/MemoryProxyNode.java	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/MemoryProxyNode.java	Mon Apr 28 11:18:15 2014 +0200
@@ -23,10 +23,10 @@
 package com.oracle.graal.nodes;
 
 import com.oracle.graal.api.meta.*;
+import com.oracle.graal.compiler.common.type.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.nodes.extended.*;
 import com.oracle.graal.nodes.spi.*;
-import com.oracle.graal.nodes.type.*;
 
 @NodeInfo(allowedUsageTypes = {InputType.Memory})
 public class MemoryProxyNode extends ProxyNode implements MemoryProxy, LIRLowerable {
@@ -34,7 +34,7 @@
     @Input(InputType.Memory) private MemoryNode value;
     private final LocationIdentity identity;
 
-    public MemoryProxyNode(MemoryNode value, AbstractBeginNode exit, LocationIdentity identity) {
+    public MemoryProxyNode(MemoryNode value, BeginNode exit, LocationIdentity identity) {
         super(StampFactory.forVoid(), exit);
         this.value = value;
         this.identity = identity;
diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/MergeNode.java
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/MergeNode.java	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/MergeNode.java	Mon Apr 28 11:18:15 2014 +0200
@@ -124,26 +124,18 @@
     }
 
     public NodeIterable phis() {
-        return this.usages().filter(PhiNode.class).filter(new NodePredicate() {
-
-            @Override
-            public boolean apply(Node n) {
-                return ((PhiNode) n).merge() == MergeNode.this;
-            }
-        });
+        return this.usages().filter(PhiNode.class).filter(this::isPhiAtMerge);
     }
 
     @Override
     public NodeIterable anchored() {
-        return super.anchored().filter(isNotA(PhiNode.class).or(new NodePredicate() {
-
-            @Override
-            public boolean apply(Node n) {
-                return ((PhiNode) n).merge() != MergeNode.this;
-            }
-        }));
+        return super.anchored().filter(n -> !isPhiAtMerge(n));
     }
 
+    /**
+     * This simplify method can deal with a null value for tool, so that it can be used outside of
+     * canonicalization.
+     */
     @Override
     public void simplify(SimplifierTool tool) {
         FixedNode next = next();
@@ -163,10 +155,8 @@
                 return;
             }
             for (PhiNode phi : phis()) {
-                for (Node usage : phi.usages().filter(isNotA(FrameState.class))) {
-                    if (!merge.isPhiAtMerge(usage)) {
-                        return;
-                    }
+                if (phi.usages().filter(isNotA(VirtualState.class)).and(node -> !merge.isPhiAtMerge(node)).isNotEmpty()) {
+                    return;
                 }
             }
             Debug.log("Split %s into ends for %s.", this, merge);
@@ -194,7 +184,9 @@
                 this.removeEnd(end);
                 end.replaceAtPredecessor(newEnd);
                 end.safeDelete();
-                tool.addToWorkList(newEnd.predecessor()); // ?
+                if (tool != null) {
+                    tool.addToWorkList(newEnd.predecessor());
+                }
             }
             graph().reduceTrivialMerge(this);
         } else if (next instanceof ReturnNode) {
diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/ParameterNode.java
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/ParameterNode.java	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/ParameterNode.java	Mon Apr 28 11:18:15 2014 +0200
@@ -22,8 +22,8 @@
  */
 package com.oracle.graal.nodes;
 
+import com.oracle.graal.compiler.common.type.*;
 import com.oracle.graal.graph.*;
-import com.oracle.graal.nodes.type.*;
 
 /**
  * The {@code Parameter} instruction is a placeholder for an incoming argument to a function call.
diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/PhiNode.java
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/PhiNode.java	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/PhiNode.java	Mon Apr 28 11:18:15 2014 +0200
@@ -22,10 +22,10 @@
  */
 package com.oracle.graal.nodes;
 
+import com.oracle.graal.compiler.common.type.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.graph.spi.*;
 import com.oracle.graal.nodes.calc.*;
-import com.oracle.graal.nodes.type.*;
 
 public abstract class PhiNode extends FloatingNode {
 
diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/PiArrayNode.java
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/PiArrayNode.java	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/PiArrayNode.java	Mon Apr 28 11:18:15 2014 +0200
@@ -22,11 +22,11 @@
  */
 package com.oracle.graal.nodes;
 
+import com.oracle.graal.compiler.common.type.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.graph.spi.*;
 import com.oracle.graal.nodes.java.*;
 import com.oracle.graal.nodes.spi.*;
-import com.oracle.graal.nodes.type.*;
 
 /**
  * A {@link PiNode} that also provides an array length in addition to a more refined stamp. A usage
diff -r 3dde8d8c95b8 -r 40d0022115ee 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	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/PiNode.java	Mon Apr 28 11:18:15 2014 +0200
@@ -25,6 +25,7 @@
 //JaCoCo Exclude
 
 import com.oracle.graal.api.meta.*;
+import com.oracle.graal.compiler.common.type.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.graph.spi.*;
 import com.oracle.graal.nodes.extended.*;
@@ -58,7 +59,7 @@
     }
 
     public PiNode(ValueNode object, ResolvedJavaType toType, boolean exactType, boolean nonNull) {
-        this(object, StampFactory.object(toType, exactType, nonNull || ObjectStamp.isObjectNonNull(object.stamp())));
+        this(object, StampFactory.object(toType, exactType, nonNull || StampTool.isObjectNonNull(object.stamp())));
     }
 
     @Override
@@ -79,7 +80,7 @@
     @Override
     public void virtualize(VirtualizerTool tool) {
         State state = tool.getObjectState(object);
-        if (state != null && state.getState() == EscapeState.Virtual && ObjectStamp.typeOrNull(this) != null && ObjectStamp.typeOrNull(this).isAssignableFrom(state.getVirtualObject().type())) {
+        if (state != null && state.getState() == EscapeState.Virtual && StampTool.typeOrNull(this) != null && StampTool.typeOrNull(this).isAssignableFrom(state.getVirtualObject().type())) {
             tool.replaceWithVirtual(state.getVirtualObject());
         }
     }
diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/ProxyNode.java
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/ProxyNode.java	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/ProxyNode.java	Mon Apr 28 11:18:15 2014 +0200
@@ -23,11 +23,11 @@
 package com.oracle.graal.nodes;
 
 import com.oracle.graal.api.meta.*;
+import com.oracle.graal.compiler.common.type.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.graph.Node.ValueNumberable;
 import com.oracle.graal.nodes.calc.*;
 import com.oracle.graal.nodes.extended.*;
-import com.oracle.graal.nodes.type.*;
 
 /**
  * A proxy is inserted at loop exits for any value that is created inside the loop (i.e. was not
@@ -35,9 +35,9 @@
  */
 public abstract class ProxyNode extends FloatingNode implements IterableNodeType, ValueNumberable {
 
-    @Input(InputType.Association) private AbstractBeginNode proxyPoint;
+    @Input(InputType.Association) private BeginNode proxyPoint;
 
-    public ProxyNode(Stamp stamp, AbstractBeginNode proxyPoint) {
+    public ProxyNode(Stamp stamp, BeginNode proxyPoint) {
         super(stamp);
         assert proxyPoint != null;
         this.proxyPoint = proxyPoint;
@@ -45,7 +45,7 @@
 
     public abstract ValueNode value();
 
-    public AbstractBeginNode proxyPoint() {
+    public BeginNode proxyPoint() {
         return proxyPoint;
     }
 
@@ -57,15 +57,15 @@
         return super.verify();
     }
 
-    public static MemoryProxyNode forMemory(MemoryNode value, AbstractBeginNode exit, LocationIdentity location, StructuredGraph graph) {
+    public static MemoryProxyNode forMemory(MemoryNode value, BeginNode exit, LocationIdentity location, StructuredGraph graph) {
         return graph.unique(new MemoryProxyNode(value, exit, location));
     }
 
-    public static ValueProxyNode forValue(ValueNode value, AbstractBeginNode exit, StructuredGraph graph) {
+    public static ValueProxyNode forValue(ValueNode value, BeginNode exit, StructuredGraph graph) {
         return graph.unique(new ValueProxyNode(value, exit));
     }
 
-    public static GuardProxyNode forGuard(GuardingNode value, AbstractBeginNode exit, StructuredGraph graph) {
+    public static GuardProxyNode forGuard(GuardingNode value, BeginNode exit, StructuredGraph graph) {
         return graph.unique(new GuardProxyNode(value, exit));
     }
 }
diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/ReturnNode.java
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/ReturnNode.java	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/ReturnNode.java	Mon Apr 28 11:18:15 2014 +0200
@@ -22,9 +22,9 @@
  */
 package com.oracle.graal.nodes;
 
+import com.oracle.graal.compiler.common.type.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.nodes.spi.*;
-import com.oracle.graal.nodes.type.*;
 
 public final class ReturnNode extends ControlSinkNode implements LIRLowerable, IterableNodeType {
 
diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/SafepointNode.java
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/SafepointNode.java	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/SafepointNode.java	Mon Apr 28 11:18:15 2014 +0200
@@ -22,8 +22,8 @@
  */
 package com.oracle.graal.nodes;
 
+import com.oracle.graal.compiler.common.type.*;
 import com.oracle.graal.nodes.spi.*;
-import com.oracle.graal.nodes.type.*;
 
 /**
  * Marks a position in the graph where a safepoint should be emitted.
diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/StateSplit.java
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/StateSplit.java	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/StateSplit.java	Mon Apr 28 11:18:15 2014 +0200
@@ -29,6 +29,8 @@
  */
 public interface StateSplit extends NodeWithState {
 
+    FixedNode asNode();
+
     /**
      * Gets the {@link FrameState} corresponding to the state of the JVM after execution of this
      * node.
diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/StructuredGraph.java
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/StructuredGraph.java	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/StructuredGraph.java	Mon Apr 28 11:18:15 2014 +0200
@@ -79,16 +79,14 @@
     private boolean isAfterFloatingReadPhase = false;
 
     /**
-     * Creates a new Graph containing a single {@link AbstractBeginNode} as the {@link #start()
-     * start} node.
+     * Creates a new Graph containing a single {@link BeginNode} as the {@link #start() start} node.
      */
     public StructuredGraph() {
         this(null, null);
     }
 
     /**
-     * Creates a new Graph containing a single {@link AbstractBeginNode} as the {@link #start()
-     * start} node.
+     * Creates a new Graph containing a single {@link BeginNode} as the {@link #start() start} node.
      */
     public StructuredGraph(String name, ResolvedJavaMethod method) {
         this(name, method, uniqueGraphIds.incrementAndGet(), INVOCATION_ENTRY_BCI);
@@ -255,8 +253,8 @@
      */
     public void removeFixed(FixedWithNextNode node) {
         assert node != null;
-        if (node instanceof AbstractBeginNode) {
-            ((AbstractBeginNode) node).prepareDelete();
+        if (node instanceof BeginNode) {
+            ((BeginNode) node).prepareDelete();
         }
         assert node.usages().isEmpty() : node + " " + node.usages();
         FixedNode next = node.next();
@@ -295,7 +293,7 @@
         node.safeDelete();
     }
 
-    public void removeSplit(ControlSplitNode node, AbstractBeginNode survivingSuccessor) {
+    public void removeSplit(ControlSplitNode node, BeginNode survivingSuccessor) {
         assert node != null;
         assert node.usages().isEmpty();
         assert survivingSuccessor != null;
@@ -304,7 +302,7 @@
         node.safeDelete();
     }
 
-    public void removeSplitPropagate(ControlSplitNode node, AbstractBeginNode survivingSuccessor) {
+    public void removeSplitPropagate(ControlSplitNode node, BeginNode survivingSuccessor) {
         assert node != null;
         assert node.usages().isEmpty();
         assert survivingSuccessor != null;
@@ -321,7 +319,7 @@
         }
     }
 
-    public void replaceSplit(ControlSplitNode node, Node replacement, AbstractBeginNode survivingSuccessor) {
+    public void replaceSplit(ControlSplitNode node, Node replacement, BeginNode survivingSuccessor) {
         if (replacement instanceof FixedWithNextNode) {
             replaceSplitWithFixed(node, (FixedWithNextNode) replacement, survivingSuccessor);
         } else {
@@ -331,7 +329,7 @@
         }
     }
 
-    public void replaceSplitWithFixed(ControlSplitNode node, FixedWithNextNode replacement, AbstractBeginNode survivingSuccessor) {
+    public void replaceSplitWithFixed(ControlSplitNode node, FixedWithNextNode replacement, BeginNode survivingSuccessor) {
         assert node != null && replacement != null && node.isAlive() && replacement.isAlive() : "cannot replace " + node + " with " + replacement;
         assert survivingSuccessor != null;
         node.clearSuccessors();
@@ -339,7 +337,7 @@
         node.replaceAndDelete(replacement);
     }
 
-    public void replaceSplitWithFloating(ControlSplitNode node, FloatingNode replacement, AbstractBeginNode survivingSuccessor) {
+    public void replaceSplitWithFloating(ControlSplitNode node, FloatingNode replacement, BeginNode survivingSuccessor) {
         assert node != null && replacement != null && node.isAlive() && replacement.isAlive() : "cannot replace " + node + " with " + replacement;
         assert survivingSuccessor != null;
         node.clearSuccessors();
diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/TypeProfileProxyNode.java
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/TypeProfileProxyNode.java	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/TypeProfileProxyNode.java	Mon Apr 28 11:18:15 2014 +0200
@@ -75,7 +75,7 @@
 
     @Override
     public Node canonical(CanonicalizerTool tool) {
-        if (ObjectStamp.isExactType(object)) {
+        if (StampTool.isExactType(object)) {
             // The profile is useless - we know the type!
             return object;
         } else if (object instanceof TypeProfileProxyNode) {
@@ -96,8 +96,8 @@
                 Debug.log("Improved profile via other profile.");
                 return TypeProfileProxyNode.create(object, newProfile);
             }
-        } else if (ObjectStamp.typeOrNull(object) != null) {
-            ResolvedJavaType type = ObjectStamp.typeOrNull(object);
+        } else if (StampTool.typeOrNull(object) != null) {
+            ResolvedJavaType type = StampTool.typeOrNull(object);
             ResolvedJavaType uniqueConcrete = type.findUniqueConcreteSubtype();
             if (uniqueConcrete != null) {
                 // Profile is useless => remove.
@@ -109,7 +109,7 @@
                 return this;
             }
             lastCheckedType = type;
-            JavaTypeProfile newProfile = this.profile.restrict(type, ObjectStamp.isObjectNonNull(object));
+            JavaTypeProfile newProfile = this.profile.restrict(type, StampTool.isObjectNonNull(object));
             if (newProfile != this.profile) {
                 Debug.log("Improved profile via static type information.");
                 if (newProfile.getTypes().length == 0) {
diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/UnaryOpLogicNode.java
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/UnaryOpLogicNode.java	Mon Apr 28 11:18:15 2014 +0200
@@ -0,0 +1,57 @@
+/*
+ * Copyright (c) 2011, 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.graal.nodes;
+
+import com.oracle.graal.api.meta.ProfilingInfo.*;
+import com.oracle.graal.nodes.extended.*;
+import com.oracle.graal.nodes.spi.*;
+
+public abstract class UnaryOpLogicNode extends LogicNode implements LIRLowerable, MemoryArithmeticLIRLowerable {
+
+    @Input private ValueNode object;
+
+    public ValueNode object() {
+        return object;
+    }
+
+    protected void setX(ValueNode object) {
+        updateUsages(this.object, object);
+        this.object = object;
+    }
+
+    public UnaryOpLogicNode(ValueNode object) {
+        assert object != null;
+        this.object = object;
+    }
+
+    public abstract TriState evaluate(ValueNode forObject);
+
+    @Override
+    public void generate(NodeLIRBuilderTool gen) {
+    }
+
+    @Override
+    public boolean generate(MemoryArithmeticLIRLowerer gen, Access access) {
+        return false;
+    }
+}
diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/UnwindNode.java
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/UnwindNode.java	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/UnwindNode.java	Mon Apr 28 11:18:15 2014 +0200
@@ -23,8 +23,8 @@
 package com.oracle.graal.nodes;
 
 import com.oracle.graal.api.meta.*;
+import com.oracle.graal.compiler.common.type.*;
 import com.oracle.graal.nodes.spi.*;
-import com.oracle.graal.nodes.type.*;
 
 /**
  * Unwinds the current frame to an exception handler in the caller frame.
diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/ValueNode.java
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/ValueNode.java	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/ValueNode.java	Mon Apr 28 11:18:15 2014 +0200
@@ -23,9 +23,9 @@
 package com.oracle.graal.nodes;
 
 import com.oracle.graal.api.meta.*;
+import com.oracle.graal.compiler.common.type.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.graph.iterators.*;
-import com.oracle.graal.nodes.type.*;
 
 /**
  * This class represents a value within the graph, including local variables, phis, and all other
@@ -92,13 +92,7 @@
         return this instanceof ConstantNode;
     }
 
-    private static final NodePredicate IS_CONSTANT = new NodePredicate() {
-
-        @Override
-        public boolean apply(Node n) {
-            return n instanceof ValueNode && ((ValueNode) n).isConstant();
-        }
-    };
+    private static final NodePredicate IS_CONSTANT = node -> node instanceof ConstantNode;
 
     public static NodePredicate isConstantPredicate() {
         return IS_CONSTANT;
diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/ValuePhiNode.java
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/ValuePhiNode.java	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/ValuePhiNode.java	Mon Apr 28 11:18:15 2014 +0200
@@ -22,6 +22,7 @@
  */
 package com.oracle.graal.nodes;
 
+import com.oracle.graal.compiler.common.type.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.graph.spi.*;
 import com.oracle.graal.nodes.type.*;
diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/ValueProxyNode.java
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/ValueProxyNode.java	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/ValueProxyNode.java	Mon Apr 28 11:18:15 2014 +0200
@@ -30,7 +30,7 @@
 
     @Input private ValueNode value;
 
-    public ValueProxyNode(ValueNode value, AbstractBeginNode proxyPoint) {
+    public ValueProxyNode(ValueNode value, BeginNode proxyPoint) {
         super(value.stamp(), proxyPoint);
         this.value = value;
     }
diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/VirtualState.java
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/VirtualState.java	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/VirtualState.java	Mon Apr 28 11:18:15 2014 +0200
@@ -45,6 +45,10 @@
 
     public abstract void applyToNonVirtual(NodeClosure closure);
 
+    /**
+     * Performs a pre-order iteration over all elements reachable from this state that are a
+     * subclass of {@link VirtualState}.
+     */
     public abstract void applyToVirtual(VirtualClosure closure);
 
     public abstract boolean isPartOfThisState(VirtualState state);
diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/AndNode.java
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/AndNode.java	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/AndNode.java	Mon Apr 28 11:18:15 2014 +0200
@@ -23,8 +23,10 @@
 package com.oracle.graal.nodes.calc;
 
 import com.oracle.graal.api.meta.*;
+import com.oracle.graal.compiler.common.type.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.graph.spi.*;
+import com.oracle.graal.lir.gen.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.extended.*;
 import com.oracle.graal.nodes.spi.*;
@@ -88,8 +90,8 @@
     }
 
     @Override
-    public void generate(NodeLIRBuilderTool gen) {
-        gen.setResult(this, gen.getLIRGeneratorTool().emitAnd(gen.operand(x()), gen.operand(y())));
+    public void generate(NodeMappableLIRBuilder builder, ArithmeticLIRGenerator gen) {
+        builder.setResult(this, gen.emitAnd(builder.operand(x()), builder.operand(y())));
     }
 
     @Override
diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/BinaryNode.java
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/BinaryNode.java	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/BinaryNode.java	Mon Apr 28 11:18:15 2014 +0200
@@ -22,10 +22,10 @@
  */
 package com.oracle.graal.nodes.calc;
 
-import com.oracle.graal.graph.*;
+import com.oracle.graal.compiler.common.*;
+import com.oracle.graal.compiler.common.type.*;
 import com.oracle.graal.graph.iterators.*;
 import com.oracle.graal.nodes.*;
-import com.oracle.graal.nodes.type.*;
 
 /**
  * The {@code BinaryNode} class is the base of arithmetic and logic operations with two inputs.
diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/BitLogicNode.java
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/BitLogicNode.java	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/BitLogicNode.java	Mon Apr 28 11:18:15 2014 +0200
@@ -22,6 +22,7 @@
  */
 package com.oracle.graal.nodes.calc;
 
+import com.oracle.graal.compiler.common.type.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.spi.*;
 import com.oracle.graal.nodes.type.*;
diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/CompareNode.java
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/CompareNode.java	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/CompareNode.java	Mon Apr 28 11:18:15 2014 +0200
@@ -23,11 +23,12 @@
 package com.oracle.graal.nodes.calc;
 
 import com.oracle.graal.api.meta.*;
+import com.oracle.graal.api.meta.ProfilingInfo.*;
+import com.oracle.graal.compiler.common.*;
+import com.oracle.graal.compiler.common.calc.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.graph.spi.*;
 import com.oracle.graal.nodes.*;
-import com.oracle.graal.nodes.extended.*;
-import com.oracle.graal.nodes.spi.*;
 
 /* TODO (thomaswue/gdub) For high-level optimization purpose the compare node should be a boolean *value* (it is currently only a helper node)
  * But in the back-end the comparison should not always be materialized (for example in x86 the comparison result will not be in a register but in a flag)
@@ -35,49 +36,32 @@
  * Compare should probably be made a value (so that it can be canonicalized for example) and in later stages some Compare usage should be transformed
  * into variants that do not materialize the value (CompareIf, CompareGuard...)
  */
-public abstract class CompareNode extends LogicNode implements Canonicalizable, LIRLowerable, MemoryArithmeticLIRLowerable {
-
-    @Input private ValueNode x;
-    @Input private ValueNode y;
-
-    public ValueNode x() {
-        return x;
-    }
-
-    public ValueNode y() {
-        return y;
-    }
+public abstract class CompareNode extends BinaryOpLogicNode {
 
     /**
      * Constructs a new Compare instruction.
-     * 
+     *
      * @param x the instruction producing the first input to the instruction
      * @param y the instruction that produces the second input to this instruction
      */
     public CompareNode(ValueNode x, ValueNode y) {
-        assert x != null && y != null && x.getKind() == y.getKind();
-        this.x = x;
-        this.y = y;
+        super(x, y);
     }
 
     /**
      * Gets the condition (comparison operation) for this instruction.
-     * 
+     *
      * @return the condition
      */
     public abstract Condition condition();
 
     /**
      * Checks whether unordered inputs mean true or false (only applies to float operations).
-     * 
+     *
      * @return {@code true} if unordered inputs produce true
      */
     public abstract boolean unorderedIsTrue();
 
-    @Override
-    public void generate(NodeLIRBuilderTool gen) {
-    }
-
     private LogicNode optimizeConditional(Constant constant, ConditionalNode conditionalNode, ConstantReflectionProvider constantReflection, Condition cond) {
         Constant trueConstant = conditionalNode.trueValue().asConstant();
         Constant falseConstant = conditionalNode.falseValue().asConstant();
@@ -102,24 +86,23 @@
         return this;
     }
 
-    protected void setX(ValueNode x) {
-        updateUsages(this.x, x);
-        this.x = x;
-    }
-
-    protected void setY(ValueNode y) {
-        updateUsages(this.y, y);
-        this.y = y;
-    }
-
     protected LogicNode optimizeNormalizeCmp(Constant constant, NormalizeCompareNode normalizeNode, boolean mirrored) {
         throw new GraalInternalError("NormalizeCompareNode connected to %s (%s %s %s)", this, constant, normalizeNode, mirrored);
     }
 
     @Override
+    public TriState evaluate(ConstantReflectionProvider constantReflection, ValueNode forX, ValueNode forY) {
+        if (x().isConstant() && y().isConstant()) {
+            return TriState.get(condition().foldCondition(x().asConstant(), y().asConstant(), constantReflection, unorderedIsTrue()));
+        }
+        return TriState.UNKNOWN;
+    }
+
+    @Override
     public Node canonical(CanonicalizerTool tool) {
-        if (x().isConstant() && y().isConstant() && tool.getMetaAccess() != null) {
-            return LogicConstantNode.forBoolean(condition().foldCondition(x().asConstant(), y().asConstant(), tool.getConstantReflection(), unorderedIsTrue()), graph());
+        Node result = super.canonical(tool);
+        if (result != this) {
+            return result;
         }
         if (x().isConstant()) {
             if (y() instanceof ConditionalNode) {
@@ -193,14 +176,4 @@
 
         return graph.unique(comparison);
     }
-
-    public boolean generate(MemoryArithmeticLIRLowerer gen, Access access) {
-        return false;
-    }
-
-    @Override
-    public boolean verify() {
-        assertTrue(x.stamp().isCompatible(y.stamp()), "stamps not compatible: %s, %s", x.stamp(), y.stamp());
-        return super.verify();
-    }
 }
diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/Condition.java
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/Condition.java	Fri Apr 25 16:21:07 2014 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,634 +0,0 @@
-/*
- * Copyright (c) 2009, 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.nodes.calc;
-
-import com.oracle.graal.api.code.*;
-import com.oracle.graal.api.meta.*;
-import com.oracle.graal.graph.*;
-
-/**
- * Condition codes used in conditionals.
- */
-public enum Condition {
-    /**
-     * Equal.
-     */
-    EQ("=="),
-
-    /**
-     * Not equal.
-     */
-    NE("!="),
-
-    /**
-     * Signed less than.
-     */
-    LT("<"),
-
-    /**
-     * Signed less than or equal.
-     */
-    LE("<="),
-
-    /**
-     * Signed greater than.
-     */
-    GT(">"),
-
-    /**
-     * Signed greater than or equal.
-     */
-    GE(">="),
-
-    /**
-     * Unsigned greater than or equal ("above than or equal").
-     */
-    AE("|>=|"),
-
-    /**
-     * Unsigned less than or equal ("below than or equal").
-     */
-    BE("|<=|"),
-
-    /**
-     * Unsigned greater than ("above than").
-     */
-    AT("|>|"),
-
-    /**
-     * Unsigned less than ("below than").
-     */
-    BT("|<|");
-
-    public final String operator;
-
-    private Condition(String operator) {
-        this.operator = operator;
-    }
-
-    public boolean check(int left, int right) {
-        switch (this) {
-            case EQ:
-                return left == right;
-            case NE:
-                return left != right;
-            case LT:
-                return left < right;
-            case LE:
-                return left <= right;
-            case GT:
-                return left > right;
-            case GE:
-                return left >= right;
-            case AE:
-                return UnsignedMath.aboveOrEqual(left, right);
-            case BE:
-                return UnsignedMath.belowOrEqual(left, right);
-            case AT:
-                return UnsignedMath.aboveThan(left, right);
-            case BT:
-                return UnsignedMath.belowThan(left, right);
-        }
-        throw new IllegalArgumentException(this.toString());
-    }
-
-    /**
-     * Given a condition and its negation, this method returns true for one of the two and false for
-     * the other one. This can be used to keep comparisons in a canonical form.
-     * 
-     * @return true if this condition is considered to be the canonical form, false otherwise.
-     */
-    public boolean isCanonical() {
-        switch (this) {
-            case EQ:
-                return true;
-            case NE:
-                return false;
-            case LT:
-                return true;
-            case LE:
-                return false;
-            case GT:
-                return false;
-            case GE:
-                return false;
-            case BT:
-                return true;
-            case BE:
-                return false;
-            case AT:
-                return false;
-            case AE:
-                return false;
-        }
-        throw new IllegalArgumentException(this.toString());
-    }
-
-    /**
-     * Returns true if the condition needs to be mirrored to get to a canonical condition. The
-     * result of the mirroring operation might still need to be negated to achieve a canonical form.
-     */
-    public boolean canonicalMirror() {
-        switch (this) {
-            case EQ:
-                return false;
-            case NE:
-                return false;
-            case LT:
-                return false;
-            case LE:
-                return true;
-            case GT:
-                return true;
-            case GE:
-                return false;
-            case BT:
-                return false;
-            case BE:
-                return true;
-            case AT:
-                return true;
-            case AE:
-                return false;
-        }
-        throw new IllegalArgumentException(this.toString());
-    }
-
-    /**
-     * Returns true if the condition needs to be negated to get to a canonical condition. The result
-     * of the negation might still need to be mirrored to achieve a canonical form.
-     */
-    public boolean canonicalNegate() {
-        switch (this) {
-            case EQ:
-                return false;
-            case NE:
-                return true;
-            case LT:
-                return false;
-            case LE:
-                return true;
-            case GT:
-                return false;
-            case GE:
-                return true;
-            case BT:
-                return false;
-            case BE:
-                return true;
-            case AT:
-                return false;
-            case AE:
-                return true;
-        }
-        throw new IllegalArgumentException(this.toString());
-    }
-
-    /**
-     * Negate this conditional.
-     * 
-     * @return the condition that represents the negation
-     */
-    public final Condition negate() {
-        switch (this) {
-            case EQ:
-                return NE;
-            case NE:
-                return EQ;
-            case LT:
-                return GE;
-            case LE:
-                return GT;
-            case GT:
-                return LE;
-            case GE:
-                return LT;
-            case BT:
-                return AE;
-            case BE:
-                return AT;
-            case AT:
-                return BE;
-            case AE:
-                return BT;
-        }
-        throw new IllegalArgumentException(this.toString());
-    }
-
-    public boolean implies(Condition other) {
-        if (other == this) {
-            return true;
-        }
-        switch (this) {
-            case EQ:
-                return other == LE || other == GE || other == BE || other == AE;
-            case NE:
-                return false;
-            case LT:
-                return other == LE || other == NE;
-            case LE:
-                return false;
-            case GT:
-                return other == GE || other == NE;
-            case GE:
-                return false;
-            case BT:
-                return other == BE || other == NE;
-            case BE:
-                return false;
-            case AT:
-                return other == AE || other == NE;
-            case AE:
-                return false;
-        }
-        throw new IllegalArgumentException(this.toString());
-    }
-
-    /**
-     * Mirror this conditional (i.e. commute "a op b" to "b op' a")
-     * 
-     * @return the condition representing the equivalent commuted operation
-     */
-    public final Condition mirror() {
-        switch (this) {
-            case EQ:
-                return EQ;
-            case NE:
-                return NE;
-            case LT:
-                return GT;
-            case LE:
-                return GE;
-            case GT:
-                return LT;
-            case GE:
-                return LE;
-            case BT:
-                return AT;
-            case BE:
-                return AE;
-            case AT:
-                return BT;
-            case AE:
-                return BE;
-        }
-        throw new IllegalArgumentException();
-    }
-
-    /**
-     * Returns true if this condition represents an unsigned comparison. EQ and NE are not
-     * considered to be unsigned.
-     */
-    public final boolean isUnsigned() {
-        return this == Condition.BT || this == Condition.BE || this == Condition.AT || this == Condition.AE;
-    }
-
-    /**
-     * Checks if this conditional operation is commutative.
-     * 
-     * @return {@code true} if this operation is commutative
-     */
-    public final boolean isCommutative() {
-        return this == EQ || this == NE;
-    }
-
-    /**
-     * Attempts to fold a comparison between two constants and return the result.
-     * 
-     * @param lt the constant on the left side of the comparison
-     * @param rt the constant on the right side of the comparison
-     * @param constantReflection needed to compare constants
-     * @return {@link Boolean#TRUE} if the comparison is known to be true, {@link Boolean#FALSE} if
-     *         the comparison is known to be false
-     */
-    public boolean foldCondition(Constant lt, Constant rt, ConstantReflectionProvider constantReflection) {
-        assert !lt.getKind().isNumericFloat() && !rt.getKind().isNumericFloat();
-        return foldCondition(lt, rt, constantReflection, false);
-    }
-
-    /**
-     * Attempts to fold a comparison between two constants and return the result.
-     * 
-     * @param lt the constant on the left side of the comparison
-     * @param rt the constant on the right side of the comparison
-     * @param constantReflection needed to compare constants
-     * @param unorderedIsTrue true if an undecided float comparison should result in "true"
-     * @return true if the comparison is known to be true, false if the comparison is known to be
-     *         false
-     */
-    public boolean foldCondition(Constant lt, Constant rt, ConstantReflectionProvider constantReflection, boolean unorderedIsTrue) {
-        switch (lt.getKind()) {
-            case Boolean:
-            case Byte:
-            case Char:
-            case Short:
-            case Int: {
-                int x = lt.asInt();
-                int y = rt.asInt();
-                switch (this) {
-                    case EQ:
-                        return x == y;
-                    case NE:
-                        return x != y;
-                    case LT:
-                        return x < y;
-                    case LE:
-                        return x <= y;
-                    case GT:
-                        return x > y;
-                    case GE:
-                        return x >= y;
-                    case AE:
-                        return UnsignedMath.aboveOrEqual(x, y);
-                    case BE:
-                        return UnsignedMath.belowOrEqual(x, y);
-                    case AT:
-                        return UnsignedMath.aboveThan(x, y);
-                    case BT:
-                        return UnsignedMath.belowThan(x, y);
-                    default:
-                        throw new GraalInternalError("expected condition: %s", this);
-                }
-            }
-            case Long: {
-                long x = lt.asLong();
-                long y = rt.asLong();
-                switch (this) {
-                    case EQ:
-                        return x == y;
-                    case NE:
-                        return x != y;
-                    case LT:
-                        return x < y;
-                    case LE:
-                        return x <= y;
-                    case GT:
-                        return x > y;
-                    case GE:
-                        return x >= y;
-                    case AE:
-                        return UnsignedMath.aboveOrEqual(x, y);
-                    case BE:
-                        return UnsignedMath.belowOrEqual(x, y);
-                    case AT:
-                        return UnsignedMath.aboveThan(x, y);
-                    case BT:
-                        return UnsignedMath.belowThan(x, y);
-                    default:
-                        throw new GraalInternalError("expected condition: %s", this);
-                }
-            }
-            case Object: {
-                Boolean equal = constantReflection.constantEquals(lt, rt);
-                if (equal != null) {
-                    switch (this) {
-                        case EQ:
-                            return equal.booleanValue();
-                        case NE:
-                            return !equal.booleanValue();
-                        default:
-                            throw new GraalInternalError("expected condition: %s", this);
-                    }
-                }
-            }
-            case Float: {
-                float x = lt.asFloat();
-                float y = rt.asFloat();
-                if (Float.isNaN(x) || Float.isNaN(y)) {
-                    return unorderedIsTrue;
-                }
-                switch (this) {
-                    case EQ:
-                        return x == y;
-                    case NE:
-                        return x != y;
-                    case LT:
-                        return x < y;
-                    case LE:
-                        return x <= y;
-                    case GT:
-                        return x > y;
-                    case GE:
-                        return x >= y;
-                    default:
-                        throw new GraalInternalError("expected condition: %s", this);
-                }
-            }
-            case Double: {
-                double x = lt.asDouble();
-                double y = rt.asDouble();
-                if (Double.isNaN(x) || Double.isNaN(y)) {
-                    return unorderedIsTrue;
-                }
-                switch (this) {
-                    case EQ:
-                        return x == y;
-                    case NE:
-                        return x != y;
-                    case LT:
-                        return x < y;
-                    case LE:
-                        return x <= y;
-                    case GT:
-                        return x > y;
-                    case GE:
-                        return x >= y;
-                    default:
-                        throw new GraalInternalError("expected condition: %s", this);
-                }
-            }
-            default:
-                throw new GraalInternalError("expected value kind %s while folding condition: %s", lt.getKind(), this);
-        }
-    }
-
-    public Condition join(Condition other) {
-        if (other == this) {
-            return this;
-        }
-        switch (this) {
-            case EQ:
-                if (other == LE || other == GE || other == BE || other == AE) {
-                    return EQ;
-                } else {
-                    return null;
-                }
-            case NE:
-                if (other == LT || other == GT || other == BT || other == AT) {
-                    return other;
-                } else if (other == LE) {
-                    return LT;
-                } else if (other == GE) {
-                    return GT;
-                } else if (other == BE) {
-                    return BT;
-                } else if (other == AE) {
-                    return AT;
-                } else {
-                    return null;
-                }
-            case LE:
-                if (other == GE || other == EQ) {
-                    return EQ;
-                } else if (other == NE || other == LT) {
-                    return LT;
-                } else {
-                    return null;
-                }
-            case LT:
-                if (other == NE || other == LE) {
-                    return LT;
-                } else {
-                    return null;
-                }
-            case GE:
-                if (other == LE || other == EQ) {
-                    return EQ;
-                } else if (other == NE || other == GT) {
-                    return GT;
-                } else {
-                    return null;
-                }
-            case GT:
-                if (other == NE || other == GE) {
-                    return GT;
-                } else {
-                    return null;
-                }
-            case BE:
-                if (other == AE || other == EQ) {
-                    return EQ;
-                } else if (other == NE || other == BT) {
-                    return BT;
-                } else {
-                    return null;
-                }
-            case BT:
-                if (other == NE || other == BE) {
-                    return BT;
-                } else {
-                    return null;
-                }
-            case AE:
-                if (other == BE || other == EQ) {
-                    return EQ;
-                } else if (other == NE || other == AT) {
-                    return AT;
-                } else {
-                    return null;
-                }
-            case AT:
-                if (other == NE || other == AE) {
-                    return AT;
-                } else {
-                    return null;
-                }
-        }
-        throw new IllegalArgumentException(this.toString());
-    }
-
-    public Condition meet(Condition other) {
-        if (other == this) {
-            return this;
-        }
-        switch (this) {
-            case EQ:
-                if (other == LE || other == GE || other == BE || other == AE) {
-                    return other;
-                } else if (other == LT) {
-                    return LE;
-                } else if (other == GT) {
-                    return GE;
-                } else if (other == BT) {
-                    return BE;
-                } else if (other == AT) {
-                    return AE;
-                } else {
-                    return null;
-                }
-            case NE:
-                if (other == LT || other == GT || other == BT || other == AT) {
-                    return NE;
-                } else {
-                    return null;
-                }
-            case LE:
-                if (other == EQ || other == LT) {
-                    return LE;
-                } else {
-                    return null;
-                }
-            case LT:
-                if (other == EQ || other == LE) {
-                    return LE;
-                } else if (other == NE || other == GT) {
-                    return NE;
-                } else {
-                    return null;
-                }
-            case GE:
-                if (other == EQ || other == GT) {
-                    return GE;
-                } else {
-                    return null;
-                }
-            case GT:
-                if (other == EQ || other == GE) {
-                    return GE;
-                } else if (other == NE || other == LT) {
-                    return NE;
-                } else {
-                    return null;
-                }
-            case BE:
-                if (other == EQ || other == BT) {
-                    return BE;
-                } else {
-                    return null;
-                }
-            case BT:
-                if (other == EQ || other == BE) {
-                    return BE;
-                } else if (other == NE || other == AT) {
-                    return NE;
-                } else {
-                    return null;
-                }
-            case AE:
-                if (other == EQ || other == AT) {
-                    return AE;
-                } else {
-                    return null;
-                }
-            case AT:
-                if (other == EQ || other == AE) {
-                    return AE;
-                } else if (other == NE || other == BT) {
-                    return NE;
-                } else {
-                    return null;
-                }
-        }
-        throw new IllegalArgumentException(this.toString());
-    }
-}
diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/ConditionalNode.java
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/ConditionalNode.java	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/ConditionalNode.java	Mon Apr 28 11:18:15 2014 +0200
@@ -25,12 +25,13 @@
 import static com.oracle.graal.nodes.calc.CompareNode.*;
 
 import com.oracle.graal.api.meta.*;
+import com.oracle.graal.compiler.common.calc.*;
+import com.oracle.graal.compiler.common.type.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.graph.spi.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.java.*;
 import com.oracle.graal.nodes.spi.*;
-import com.oracle.graal.nodes.type.*;
 
 /**
  * The {@code ConditionalNode} class represents a comparison that yields one of two values. Note
diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/ConvertNode.java
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/ConvertNode.java	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/ConvertNode.java	Mon Apr 28 11:18:15 2014 +0200
@@ -24,8 +24,8 @@
 
 import com.oracle.graal.api.code.*;
 import com.oracle.graal.api.meta.*;
+import com.oracle.graal.compiler.common.type.*;
 import com.oracle.graal.nodes.*;
-import com.oracle.graal.nodes.type.*;
 
 /**
  * Represents a conversion between primitive types.
diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/FixedBinaryNode.java
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/FixedBinaryNode.java	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/FixedBinaryNode.java	Mon Apr 28 11:18:15 2014 +0200
@@ -22,8 +22,8 @@
  */
 package com.oracle.graal.nodes.calc;
 
+import com.oracle.graal.compiler.common.type.*;
 import com.oracle.graal.nodes.*;
-import com.oracle.graal.nodes.type.*;
 
 public abstract class FixedBinaryNode extends DeoptimizingFixedWithNextNode {
 
diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/FloatAddNode.java
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/FloatAddNode.java	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/FloatAddNode.java	Mon Apr 28 11:18:15 2014 +0200
@@ -23,12 +23,13 @@
 package com.oracle.graal.nodes.calc;
 
 import com.oracle.graal.api.meta.*;
+import com.oracle.graal.compiler.common.type.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.graph.spi.*;
+import com.oracle.graal.lir.gen.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.extended.*;
 import com.oracle.graal.nodes.spi.*;
-import com.oracle.graal.nodes.type.*;
 
 @NodeInfo(shortName = "+")
 public final class FloatAddNode extends FloatArithmeticNode implements Canonicalizable {
@@ -65,20 +66,20 @@
     }
 
     @Override
-    public void generate(NodeLIRBuilderTool gen) {
-        Value op1 = gen.operand(x());
-        Value op2 = gen.operand(y());
-        if (!y().isConstant() && !livesLonger(this, y(), gen)) {
+    public void generate(NodeMappableLIRBuilder builder, ArithmeticLIRGenerator gen) {
+        Value op1 = builder.operand(x());
+        Value op2 = builder.operand(y());
+        if (!y().isConstant() && !livesLonger(this, y(), builder)) {
             Value op = op1;
             op1 = op2;
             op2 = op;
         }
-        gen.setResult(this, gen.getLIRGeneratorTool().emitAdd(op1, op2));
+        builder.setResult(this, gen.emitAdd(op1, op2));
     }
 
-    public static boolean livesLonger(ValueNode after, ValueNode value, NodeLIRBuilderTool gen) {
+    public static boolean livesLonger(ValueNode after, ValueNode value, NodeMappableLIRBuilder builder) {
         for (Node usage : value.usages()) {
-            if (usage != after && usage instanceof ValueNode && gen.hasOperand(((ValueNode) usage))) {
+            if (usage != after && usage instanceof ValueNode && builder.hasOperand(((ValueNode) usage))) {
                 return true;
             }
         }
diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/FloatArithmeticNode.java
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/FloatArithmeticNode.java	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/FloatArithmeticNode.java	Mon Apr 28 11:18:15 2014 +0200
@@ -22,9 +22,9 @@
  */
 package com.oracle.graal.nodes.calc;
 
+import com.oracle.graal.compiler.common.type.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.spi.*;
-import com.oracle.graal.nodes.type.*;
 
 public abstract class FloatArithmeticNode extends BinaryNode implements ArithmeticLIRLowerable, MemoryArithmeticLIRLowerable {
 
diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/FloatConvertNode.java
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/FloatConvertNode.java	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/FloatConvertNode.java	Mon Apr 28 11:18:15 2014 +0200
@@ -23,12 +23,15 @@
 package com.oracle.graal.nodes.calc;
 
 import com.oracle.graal.api.meta.*;
+import com.oracle.graal.compiler.common.*;
+import com.oracle.graal.compiler.common.calc.*;
+import com.oracle.graal.compiler.common.type.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.graph.spi.*;
+import com.oracle.graal.lir.gen.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.extended.*;
 import com.oracle.graal.nodes.spi.*;
-import com.oracle.graal.nodes.type.*;
 
 /**
  * A {@code FloatConvert} converts between integers and floating point numbers according to Java
@@ -36,46 +39,6 @@
  */
 public class FloatConvertNode extends ConvertNode implements Canonicalizable, Lowerable, ArithmeticLIRLowerable, MemoryArithmeticLIRLowerable {
 
-    public enum FloatConvert {
-        F2I,
-        D2I,
-        F2L,
-        D2L,
-        I2F,
-        L2F,
-        D2F,
-        I2D,
-        L2D,
-        F2D;
-
-        public FloatConvert reverse() {
-            switch (this) {
-                case D2F:
-                    return F2D;
-                case D2I:
-                    return I2D;
-                case D2L:
-                    return L2D;
-                case F2D:
-                    return D2F;
-                case F2I:
-                    return I2F;
-                case F2L:
-                    return L2F;
-                case I2D:
-                    return D2I;
-                case I2F:
-                    return F2I;
-                case L2D:
-                    return D2L;
-                case L2F:
-                    return F2L;
-                default:
-                    throw GraalInternalError.shouldNotReachHere();
-            }
-        }
-    }
-
     private final FloatConvert op;
 
     public FloatConvertNode(FloatConvert op, ValueNode input) {
@@ -201,17 +164,11 @@
         tool.getLowerer().lower(this, tool);
     }
 
-    public void generate(NodeLIRBuilderTool gen) {
-        gen.setResult(this, gen.getLIRGeneratorTool().emitFloatConvert(op, gen.operand(getInput())));
+    public void generate(NodeMappableLIRBuilder builder, ArithmeticLIRGenerator gen) {
+        builder.setResult(this, gen.emitFloatConvert(op, builder.operand(getInput())));
     }
 
     public boolean generate(MemoryArithmeticLIRLowerer gen, Access access) {
-        Kind kind = access.accessLocation().getValueKind();
-        if (kind != kind.getStackKind()) {
-            // Doesn't work for subword operations
-            return false;
-        }
-
         Value result = gen.emitFloatConvertMemory(getOp(), access);
         if (result != null) {
             gen.setResult(this, result);
diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/FloatDivNode.java
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/FloatDivNode.java	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/FloatDivNode.java	Mon Apr 28 11:18:15 2014 +0200
@@ -23,12 +23,13 @@
 package com.oracle.graal.nodes.calc;
 
 import com.oracle.graal.api.meta.*;
+import com.oracle.graal.compiler.common.type.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.graph.spi.*;
+import com.oracle.graal.lir.gen.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.extended.*;
 import com.oracle.graal.nodes.spi.*;
-import com.oracle.graal.nodes.type.*;
 
 @NodeInfo(shortName = "/")
 public final class FloatDivNode extends FloatArithmeticNode implements Canonicalizable {
@@ -57,8 +58,8 @@
     }
 
     @Override
-    public void generate(NodeLIRBuilderTool gen) {
-        gen.setResult(this, gen.getLIRGeneratorTool().emitDiv(gen.operand(x()), gen.operand(y()), null));
+    public void generate(NodeMappableLIRBuilder builder, ArithmeticLIRGenerator gen) {
+        builder.setResult(this, gen.emitDiv(builder.operand(x()), builder.operand(y()), null));
     }
 
     @Override
diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/FloatEqualsNode.java
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/FloatEqualsNode.java	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/FloatEqualsNode.java	Mon Apr 28 11:18:15 2014 +0200
@@ -22,16 +22,20 @@
  */
 package com.oracle.graal.nodes.calc;
 
+import com.oracle.graal.api.meta.*;
+import com.oracle.graal.api.meta.ProfilingInfo.*;
+import com.oracle.graal.compiler.common.calc.*;
+import com.oracle.graal.compiler.common.type.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.nodes.*;
-import com.oracle.graal.nodes.type.*;
+import com.oracle.graal.nodes.util.*;
 
 @NodeInfo(shortName = "==")
 public final class FloatEqualsNode extends CompareNode {
 
     /**
      * Constructs a new floating point equality comparison node.
-     * 
+     *
      * @param x the instruction producing the first input to the instruction
      * @param y the instruction that produces the second input to this instruction
      */
@@ -50,4 +54,18 @@
     public boolean unorderedIsTrue() {
         return false;
     }
+
+    @Override
+    public TriState evaluate(ConstantReflectionProvider constantReflection, ValueNode forX, ValueNode forY) {
+        if (forX.stamp() instanceof FloatStamp && forY.stamp() instanceof FloatStamp) {
+            FloatStamp xStamp = (FloatStamp) forX.stamp();
+            FloatStamp yStamp = (FloatStamp) forY.stamp();
+            if (GraphUtil.unproxify(forX) == GraphUtil.unproxify(forY) && xStamp.isNonNaN() && yStamp.isNonNaN()) {
+                return TriState.TRUE;
+            } else if (xStamp.alwaysDistinct(yStamp)) {
+                return TriState.FALSE;
+            }
+        }
+        return super.evaluate(constantReflection, forX, forY);
+    }
 }
diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/FloatLessThanNode.java
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/FloatLessThanNode.java	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/FloatLessThanNode.java	Mon Apr 28 11:18:15 2014 +0200
@@ -22,10 +22,13 @@
  */
 package com.oracle.graal.nodes.calc;
 
+import com.oracle.graal.api.meta.*;
+import com.oracle.graal.api.meta.ProfilingInfo.TriState;
+import com.oracle.graal.compiler.common.calc.*;
+import com.oracle.graal.compiler.common.type.*;
 import com.oracle.graal.graph.*;
-import com.oracle.graal.graph.spi.*;
 import com.oracle.graal.nodes.*;
-import com.oracle.graal.nodes.type.*;
+import com.oracle.graal.nodes.util.*;
 
 @NodeInfo(shortName = "<")
 public final class FloatLessThanNode extends CompareNode {
@@ -34,7 +37,7 @@
 
     /**
      * Constructs a new floating point comparison node.
-     * 
+     *
      * @param x the instruction producing the first input to the instruction
      * @param y the instruction that produces the second input to this instruction
      * @param unorderedIsTrue whether a comparison that is undecided (involving NaNs, etc.) leads to
@@ -58,10 +61,10 @@
     }
 
     @Override
-    public Node canonical(CanonicalizerTool tool) {
-        if (x() == y() && !unorderedIsTrue()) {
-            return LogicConstantNode.contradiction(graph());
+    public TriState evaluate(ConstantReflectionProvider constantReflection, ValueNode forX, ValueNode forY) {
+        if (GraphUtil.unproxify(forX) == GraphUtil.unproxify(forY) && !unorderedIsTrue()) {
+            return TriState.FALSE;
         }
-        return super.canonical(tool);
+        return super.evaluate(constantReflection, forX, forY);
     }
 }
diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/FloatMulNode.java
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/FloatMulNode.java	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/FloatMulNode.java	Mon Apr 28 11:18:15 2014 +0200
@@ -23,12 +23,13 @@
 package com.oracle.graal.nodes.calc;
 
 import com.oracle.graal.api.meta.*;
+import com.oracle.graal.compiler.common.type.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.graph.spi.*;
+import com.oracle.graal.lir.gen.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.extended.*;
 import com.oracle.graal.nodes.spi.*;
-import com.oracle.graal.nodes.type.*;
 
 @NodeInfo(shortName = "*")
 public final class FloatMulNode extends FloatArithmeticNode implements Canonicalizable {
@@ -60,15 +61,15 @@
     }
 
     @Override
-    public void generate(NodeLIRBuilderTool gen) {
-        Value op1 = gen.operand(x());
-        Value op2 = gen.operand(y());
-        if (!y().isConstant() && !FloatAddNode.livesLonger(this, y(), gen)) {
+    public void generate(NodeMappableLIRBuilder builder, ArithmeticLIRGenerator gen) {
+        Value op1 = builder.operand(x());
+        Value op2 = builder.operand(y());
+        if (!y().isConstant() && !FloatAddNode.livesLonger(this, y(), builder)) {
             Value op = op1;
             op1 = op2;
             op2 = op;
         }
-        gen.setResult(this, gen.getLIRGeneratorTool().emitMul(op1, op2));
+        builder.setResult(this, gen.emitMul(op1, op2));
     }
 
     @Override
diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/FloatRemNode.java
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/FloatRemNode.java	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/FloatRemNode.java	Mon Apr 28 11:18:15 2014 +0200
@@ -23,12 +23,13 @@
 package com.oracle.graal.nodes.calc;
 
 import com.oracle.graal.api.meta.*;
+import com.oracle.graal.compiler.common.type.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.graph.spi.*;
+import com.oracle.graal.lir.gen.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.extended.*;
 import com.oracle.graal.nodes.spi.*;
-import com.oracle.graal.nodes.type.*;
 
 @NodeInfo(shortName = "%")
 public final class FloatRemNode extends FloatArithmeticNode implements Canonicalizable {
@@ -57,8 +58,8 @@
     }
 
     @Override
-    public void generate(NodeLIRBuilderTool gen) {
-        gen.setResult(this, gen.getLIRGeneratorTool().emitRem(gen.operand(x()), gen.operand(y()), null));
+    public void generate(NodeMappableLIRBuilder builder, ArithmeticLIRGenerator gen) {
+        builder.setResult(this, gen.emitRem(builder.operand(x()), builder.operand(y()), null));
     }
 
     @Override
diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/FloatSubNode.java
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/FloatSubNode.java	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/FloatSubNode.java	Mon Apr 28 11:18:15 2014 +0200
@@ -23,12 +23,13 @@
 package com.oracle.graal.nodes.calc;
 
 import com.oracle.graal.api.meta.*;
+import com.oracle.graal.compiler.common.type.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.graph.spi.*;
+import com.oracle.graal.lir.gen.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.extended.*;
 import com.oracle.graal.nodes.spi.*;
-import com.oracle.graal.nodes.type.*;
 
 @NodeInfo(shortName = "-")
 public final class FloatSubNode extends FloatArithmeticNode implements Canonicalizable {
@@ -76,8 +77,8 @@
     }
 
     @Override
-    public void generate(NodeLIRBuilderTool gen) {
-        gen.setResult(this, gen.getLIRGeneratorTool().emitSub(gen.operand(x()), gen.operand(y())));
+    public void generate(NodeMappableLIRBuilder builder, ArithmeticLIRGenerator gen) {
+        builder.setResult(this, gen.emitSub(builder.operand(x()), builder.operand(y())));
     }
 
     @Override
diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/FloatingNode.java
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/FloatingNode.java	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/FloatingNode.java	Mon Apr 28 11:18:15 2014 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2011, 2014, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -22,13 +22,18 @@
  */
 package com.oracle.graal.nodes.calc;
 
+import com.oracle.graal.compiler.common.type.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.nodes.*;
-import com.oracle.graal.nodes.type.*;
 
 public abstract class FloatingNode extends ValueNode implements Node.ValueNumberable {
 
     public FloatingNode(Stamp stamp) {
         super(stamp);
     }
+
+    @Override
+    public FloatingNode asNode() {
+        return this;
+    }
 }
diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IntegerAddNode.java
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IntegerAddNode.java	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IntegerAddNode.java	Mon Apr 28 11:18:15 2014 +0200
@@ -23,8 +23,10 @@
 package com.oracle.graal.nodes.calc;
 
 import com.oracle.graal.api.meta.*;
+import com.oracle.graal.compiler.common.type.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.graph.spi.*;
+import com.oracle.graal.lir.gen.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.extended.*;
 import com.oracle.graal.nodes.spi.*;
@@ -89,16 +91,16 @@
     }
 
     @Override
-    public void generate(NodeLIRBuilderTool gen) {
-        Value op1 = gen.operand(x());
+    public void generate(NodeMappableLIRBuilder builder, ArithmeticLIRGenerator gen) {
+        Value op1 = builder.operand(x());
         assert op1 != null : x() + ", this=" + this;
-        Value op2 = gen.operand(y());
-        if (!y().isConstant() && !FloatAddNode.livesLonger(this, y(), gen)) {
+        Value op2 = builder.operand(y());
+        if (!y().isConstant() && !FloatAddNode.livesLonger(this, y(), builder)) {
             Value op = op1;
             op1 = op2;
             op2 = op;
         }
-        gen.setResult(this, gen.getLIRGeneratorTool().emitAdd(op1, op2));
+        builder.setResult(this, gen.emitAdd(op1, op2));
     }
 
     @Override
diff -r 3dde8d8c95b8 -r 40d0022115ee 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	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IntegerArithmeticNode.java	Mon Apr 28 11:18:15 2014 +0200
@@ -22,6 +22,7 @@
  */
 package com.oracle.graal.nodes.calc;
 
+import com.oracle.graal.compiler.common.type.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.spi.*;
 import com.oracle.graal.nodes.type.*;
diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IntegerBelowThanNode.java
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IntegerBelowThanNode.java	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IntegerBelowThanNode.java	Mon Apr 28 11:18:15 2014 +0200
@@ -23,17 +23,20 @@
 package com.oracle.graal.nodes.calc;
 
 import com.oracle.graal.api.meta.*;
+import com.oracle.graal.api.meta.ProfilingInfo.*;
+import com.oracle.graal.compiler.common.calc.*;
+import com.oracle.graal.compiler.common.type.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.graph.spi.*;
 import com.oracle.graal.nodes.*;
-import com.oracle.graal.nodes.type.*;
+import com.oracle.graal.nodes.util.*;
 
 @NodeInfo(shortName = "|<|")
 public final class IntegerBelowThanNode extends CompareNode {
 
     /**
      * Constructs a new unsigned integer comparison node.
-     * 
+     *
      * @param x the instruction producing the first input to the instruction
      * @param y the instruction that produces the second input to this instruction
      */
@@ -54,28 +57,33 @@
     }
 
     @Override
-    public Node canonical(CanonicalizerTool tool) {
-        if (x() == y()) {
-            return LogicConstantNode.contradiction(graph());
-        } else {
-            if (x().isConstant() && x().asConstant().asLong() == 0) {
-                // 0 |<| y is the same as 0 != y
-                return graph().unique(new LogicNegationNode(CompareNode.createCompareNode(graph(), Condition.EQ, x(), y())));
-            }
-
-            if (x().stamp() instanceof IntegerStamp && y().stamp() instanceof IntegerStamp) {
-                IntegerStamp xStamp = (IntegerStamp) x().stamp();
-                IntegerStamp yStamp = (IntegerStamp) y().stamp();
-                if (yStamp.isPositive()) {
-                    if (xStamp.isPositive() && xStamp.upperBound() < yStamp.lowerBound()) {
-                        return LogicConstantNode.tautology(graph());
-                    } else if (xStamp.isStrictlyNegative() || xStamp.lowerBound() >= yStamp.upperBound()) {
-                        return LogicConstantNode.contradiction(graph());
-                    }
+    public TriState evaluate(ConstantReflectionProvider constantReflection, ValueNode forX, ValueNode forY) {
+        if (GraphUtil.unproxify(forX) == GraphUtil.unproxify(forY)) {
+            return TriState.FALSE;
+        } else if (forX.stamp() instanceof IntegerStamp && forY.stamp() instanceof IntegerStamp) {
+            IntegerStamp xStamp = (IntegerStamp) forX.stamp();
+            IntegerStamp yStamp = (IntegerStamp) forY.stamp();
+            if (yStamp.isPositive()) {
+                if (xStamp.isPositive() && xStamp.upperBound() < yStamp.lowerBound()) {
+                    return TriState.TRUE;
+                } else if (xStamp.isStrictlyNegative() || xStamp.lowerBound() >= yStamp.upperBound()) {
+                    return TriState.FALSE;
                 }
             }
         }
+        return super.evaluate(constantReflection, forX, forY);
+    }
 
-        return super.canonical(tool);
+    @Override
+    public Node canonical(CanonicalizerTool tool) {
+        Node result = super.canonical(tool);
+        if (result != this) {
+            return result;
+        }
+        if (x().isConstant() && x().asConstant().asLong() == 0) {
+            // 0 |<| y is the same as 0 != y
+            return graph().unique(new LogicNegationNode(CompareNode.createCompareNode(graph(), Condition.EQ, x(), y())));
+        }
+        return this;
     }
 }
diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IntegerConvertNode.java
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IntegerConvertNode.java	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IntegerConvertNode.java	Mon Apr 28 11:18:15 2014 +0200
@@ -23,10 +23,10 @@
 package com.oracle.graal.nodes.calc;
 
 import com.oracle.graal.api.meta.*;
+import com.oracle.graal.compiler.common.type.*;
 import com.oracle.graal.graph.spi.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.spi.*;
-import com.oracle.graal.nodes.type.*;
 
 /**
  * An {@code IntegerConvert} converts an integer to an integer of different width.
@@ -67,7 +67,7 @@
                 return getInput();
             } else if (getInput().isConstant()) {
                 Constant ret = evalConst(getInput().asConstant());
-                return ConstantNode.forIntegerBits(resultBits, false, ret.asLong(), graph());
+                return ConstantNode.forIntegerBits(resultBits, ret.asLong(), graph());
             }
         }
 
@@ -86,19 +86,11 @@
             result = graph.unique(new NarrowNode(input, toStamp.getBits()));
         } else {
             // toStamp.getBits() > fromStamp.getBits()
-            if (fromStamp.isUnsigned()) {
-                result = graph.unique(new ZeroExtendNode(input, toStamp.getBits()));
-            } else {
-                result = graph.unique(new SignExtendNode(input, toStamp.getBits()));
-            }
+            result = graph.unique(new SignExtendNode(input, toStamp.getBits()));
         }
 
         IntegerStamp resultStamp = (IntegerStamp) result.stamp();
         assert toStamp.getBits() == resultStamp.getBits();
-        if (toStamp.isUnsigned() == resultStamp.isUnsigned()) {
-            return result;
-        } else {
-            return graph.unique(new ReinterpretNode(toStamp, result));
-        }
+        return result;
     }
 }
diff -r 3dde8d8c95b8 -r 40d0022115ee 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	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IntegerDivNode.java	Mon Apr 28 11:18:15 2014 +0200
@@ -23,6 +23,7 @@
 package com.oracle.graal.nodes.calc;
 
 import com.oracle.graal.api.code.*;
+import com.oracle.graal.compiler.common.type.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.graph.spi.*;
 import com.oracle.graal.nodes.*;
@@ -107,7 +108,7 @@
 
     @Override
     public void generate(NodeLIRBuilderTool gen) {
-        gen.setResult(this, gen.getLIRGeneratorTool().emitDiv(gen.operand(x()), gen.operand(y()), this));
+        gen.setResult(this, gen.getLIRGeneratorTool().emitDiv(gen.operand(x()), gen.operand(y()), gen.state(this)));
     }
 
     @Override
diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IntegerEqualsNode.java
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IntegerEqualsNode.java	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IntegerEqualsNode.java	Mon Apr 28 11:18:15 2014 +0200
@@ -23,10 +23,12 @@
 package com.oracle.graal.nodes.calc;
 
 import com.oracle.graal.api.meta.*;
+import com.oracle.graal.api.meta.ProfilingInfo.*;
+import com.oracle.graal.compiler.common.calc.*;
+import com.oracle.graal.compiler.common.type.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.graph.spi.*;
 import com.oracle.graal.nodes.*;
-import com.oracle.graal.nodes.type.*;
 import com.oracle.graal.nodes.util.*;
 
 @NodeInfo(shortName = "==")
@@ -34,7 +36,7 @@
 
     /**
      * Constructs a new integer equality comparison node.
-     * 
+     *
      * @param x the instruction producing the first input to the instruction
      * @param y the instruction that produces the second input to this instruction
      */
@@ -70,24 +72,28 @@
     }
 
     @Override
+    public TriState evaluate(ConstantReflectionProvider constantReflection, ValueNode forX, ValueNode forY) {
+        if (GraphUtil.unproxify(forX) == GraphUtil.unproxify(forY)) {
+            return TriState.TRUE;
+        } else if (forX.stamp().alwaysDistinct(forY.stamp())) {
+            return TriState.FALSE;
+        }
+        return super.evaluate(constantReflection, forX, forY);
+    }
+
+    @Override
     public Node canonical(CanonicalizerTool tool) {
-        if (GraphUtil.unproxify(x()) == GraphUtil.unproxify(y())) {
-            return LogicConstantNode.tautology(graph());
-        } else if (x().stamp().alwaysDistinct(y().stamp())) {
-            return LogicConstantNode.contradiction(graph());
-        }
-
-        ValueNode result = canonicalizeSymmetric(x(), y());
-        if (result != null) {
+        Node result = super.canonical(tool);
+        if (result != this) {
             return result;
         }
 
-        result = canonicalizeSymmetric(y(), x());
-        if (result != null) {
+        result = canonicalizeSymmetric(x(), y());
+        if (result != this) {
             return result;
         }
 
-        return super.canonical(tool);
+        return canonicalizeSymmetric(y(), x());
     }
 
     private ValueNode canonicalizeSymmetric(ValueNode x, ValueNode y) {
@@ -132,6 +138,6 @@
                 }
             }
         }
-        return null;
+        return this;
     }
 }
diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IntegerLessThanNode.java
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IntegerLessThanNode.java	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IntegerLessThanNode.java	Mon Apr 28 11:18:15 2014 +0200
@@ -23,17 +23,20 @@
 package com.oracle.graal.nodes.calc;
 
 import com.oracle.graal.api.meta.*;
+import com.oracle.graal.api.meta.ProfilingInfo.*;
+import com.oracle.graal.compiler.common.calc.*;
+import com.oracle.graal.compiler.common.type.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.graph.spi.*;
 import com.oracle.graal.nodes.*;
-import com.oracle.graal.nodes.type.*;
+import com.oracle.graal.nodes.util.*;
 
 @NodeInfo(shortName = "<")
 public final class IntegerLessThanNode extends CompareNode {
 
     /**
      * Constructs a new integer comparison node.
-     * 
+     *
      * @param x the instruction producing the first input to the instruction
      * @param y the instruction that produces the second input to this instruction
      */
@@ -70,22 +73,32 @@
     }
 
     @Override
+    public TriState evaluate(ConstantReflectionProvider constantReflection, ValueNode forX, ValueNode forY) {
+        if (GraphUtil.unproxify(forX) == GraphUtil.unproxify(forY)) {
+            return TriState.FALSE;
+        } else if (forX.stamp() instanceof IntegerStamp && forY.stamp() instanceof IntegerStamp) {
+            IntegerStamp xStamp = (IntegerStamp) forX.stamp();
+            IntegerStamp yStamp = (IntegerStamp) forY.stamp();
+            if (xStamp.upperBound() < yStamp.lowerBound()) {
+                return TriState.TRUE;
+            } else if (xStamp.lowerBound() >= yStamp.upperBound()) {
+                return TriState.FALSE;
+            }
+        }
+        return super.evaluate(constantReflection, forX, forY);
+    }
+
+    @Override
     public Node canonical(CanonicalizerTool tool) {
-        if (x() == y()) {
-            return LogicConstantNode.contradiction(graph());
+        Node result = super.canonical(tool);
+        if (result != this) {
+            return result;
         }
         if (x().stamp() instanceof IntegerStamp && y().stamp() instanceof IntegerStamp) {
-            IntegerStamp xStamp = (IntegerStamp) x().stamp();
-            IntegerStamp yStamp = (IntegerStamp) y().stamp();
-            if (xStamp.upperBound() < yStamp.lowerBound()) {
-                return LogicConstantNode.tautology(graph());
-            } else if (xStamp.lowerBound() >= yStamp.upperBound()) {
-                return LogicConstantNode.contradiction(graph());
-            }
-            if (IntegerStamp.sameSign(xStamp, yStamp)) {
+            if (IntegerStamp.sameSign((IntegerStamp) x().stamp(), (IntegerStamp) y().stamp())) {
                 return graph().unique(new IntegerBelowThanNode(x(), y()));
             }
         }
-        return super.canonical(tool);
+        return this;
     }
 }
diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IntegerMulNode.java
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IntegerMulNode.java	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IntegerMulNode.java	Mon Apr 28 11:18:15 2014 +0200
@@ -24,12 +24,13 @@
 
 import com.oracle.graal.api.code.*;
 import com.oracle.graal.api.meta.*;
+import com.oracle.graal.compiler.common.type.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.graph.spi.*;
+import com.oracle.graal.lir.gen.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.extended.*;
 import com.oracle.graal.nodes.spi.*;
-import com.oracle.graal.nodes.type.*;
 
 @NodeInfo(shortName = "*")
 public class IntegerMulNode extends IntegerArithmeticNode implements Canonicalizable, NarrowableArithmeticNode {
@@ -75,15 +76,15 @@
     }
 
     @Override
-    public void generate(NodeLIRBuilderTool gen) {
-        Value op1 = gen.operand(x());
-        Value op2 = gen.operand(y());
-        if (!y().isConstant() && !FloatAddNode.livesLonger(this, y(), gen)) {
+    public void generate(NodeMappableLIRBuilder builder, ArithmeticLIRGenerator gen) {
+        Value op1 = builder.operand(x());
+        Value op2 = builder.operand(y());
+        if (!y().isConstant() && !FloatAddNode.livesLonger(this, y(), builder)) {
             Value op = op1;
             op1 = op2;
             op2 = op;
         }
-        gen.setResult(this, gen.getLIRGeneratorTool().emitMul(op1, op2));
+        builder.setResult(this, gen.emitMul(op1, op2));
     }
 
     @Override
diff -r 3dde8d8c95b8 -r 40d0022115ee 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	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IntegerRemNode.java	Mon Apr 28 11:18:15 2014 +0200
@@ -23,11 +23,11 @@
 package com.oracle.graal.nodes.calc;
 
 import com.oracle.graal.api.code.*;
+import com.oracle.graal.compiler.common.type.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.graph.spi.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.spi.*;
-import com.oracle.graal.nodes.type.*;
 
 @NodeInfo(shortName = "%")
 public class IntegerRemNode extends FixedBinaryNode implements Canonicalizable, Lowerable, LIRLowerable {
@@ -62,7 +62,7 @@
 
     @Override
     public void generate(NodeLIRBuilderTool gen) {
-        gen.setResult(this, gen.getLIRGeneratorTool().emitRem(gen.operand(x()), gen.operand(y()), this));
+        gen.setResult(this, gen.getLIRGeneratorTool().emitRem(gen.operand(x()), gen.operand(y()), gen.state(this)));
     }
 
     @Override
diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IntegerSubNode.java
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IntegerSubNode.java	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IntegerSubNode.java	Mon Apr 28 11:18:15 2014 +0200
@@ -23,8 +23,10 @@
 package com.oracle.graal.nodes.calc;
 
 import com.oracle.graal.api.meta.*;
+import com.oracle.graal.compiler.common.type.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.graph.spi.*;
+import com.oracle.graal.lir.gen.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.extended.*;
 import com.oracle.graal.nodes.spi.*;
@@ -117,8 +119,8 @@
     }
 
     @Override
-    public void generate(NodeLIRBuilderTool gen) {
-        gen.setResult(this, gen.getLIRGeneratorTool().emitSub(gen.operand(x()), gen.operand(y())));
+    public void generate(NodeMappableLIRBuilder builder, ArithmeticLIRGenerator gen) {
+        builder.setResult(this, gen.emitSub(builder.operand(x()), builder.operand(y())));
     }
 
     @Override
diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IntegerTestNode.java
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IntegerTestNode.java	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IntegerTestNode.java	Mon Apr 28 11:18:15 2014 +0200
@@ -22,64 +22,42 @@
  */
 package com.oracle.graal.nodes.calc;
 
-import com.oracle.graal.graph.*;
-import com.oracle.graal.graph.spi.*;
+import com.oracle.graal.api.meta.*;
+import com.oracle.graal.api.meta.ProfilingInfo.TriState;
+import com.oracle.graal.compiler.common.type.*;
 import com.oracle.graal.nodes.*;
-import com.oracle.graal.nodes.extended.*;
-import com.oracle.graal.nodes.spi.*;
-import com.oracle.graal.nodes.type.*;
 
 /**
  * This node will perform a "test" operation on its arguments. Its result is equivalent to the
  * expression "(x & y) == 0", meaning that it will return true if (and only if) no bit is set in
  * both x and y.
  */
-public class IntegerTestNode extends LogicNode implements Canonicalizable, LIRLowerable, MemoryArithmeticLIRLowerable {
-
-    @Input private ValueNode x;
-    @Input private ValueNode y;
-
-    public ValueNode x() {
-        return x;
-    }
-
-    public ValueNode y() {
-        return y;
-    }
+public class IntegerTestNode extends BinaryOpLogicNode {
 
     /**
      * Constructs a new Test instruction.
-     * 
+     *
      * @param x the instruction producing the first input to the instruction
      * @param y the instruction that produces the second input to this instruction
      */
     public IntegerTestNode(ValueNode x, ValueNode y) {
-        assert x != null && y != null && x.stamp().isCompatible(y.stamp());
-        this.x = x;
-        this.y = y;
-    }
-
-    @Override
-    public void generate(NodeLIRBuilderTool gen) {
+        super(x, y);
     }
 
     @Override
-    public Node canonical(CanonicalizerTool tool) {
-        if (x().isConstant() && y().isConstant()) {
-            return LogicConstantNode.forBoolean((x().asConstant().asLong() & y().asConstant().asLong()) == 0, graph());
+    public TriState evaluate(ConstantReflectionProvider constantReflection, ValueNode forX, ValueNode forY) {
+        if (forX.isConstant() && forY.isConstant()) {
+            return TriState.get((forX.asConstant().asLong() & forY.asConstant().asLong()) == 0);
         }
         if (x().stamp() instanceof IntegerStamp && y().stamp() instanceof IntegerStamp) {
-            IntegerStamp xStamp = (IntegerStamp) x().stamp();
-            IntegerStamp yStamp = (IntegerStamp) y().stamp();
+            IntegerStamp xStamp = (IntegerStamp) forX.stamp();
+            IntegerStamp yStamp = (IntegerStamp) forY.stamp();
             if ((xStamp.upMask() & yStamp.upMask()) == 0) {
-                return LogicConstantNode.tautology(graph());
+                return TriState.TRUE;
+            } else if ((xStamp.downMask() & yStamp.downMask()) != 0) {
+                return TriState.FALSE;
             }
         }
-        return this;
-    }
-
-    @Override
-    public boolean generate(MemoryArithmeticLIRLowerer gen, Access access) {
-        return false;
+        return TriState.UNKNOWN;
     }
 }
diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IsNullNode.java
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IsNullNode.java	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IsNullNode.java	Mon Apr 28 11:18:15 2014 +0200
@@ -23,6 +23,8 @@
 package com.oracle.graal.nodes.calc;
 
 import com.oracle.graal.api.meta.*;
+import com.oracle.graal.api.meta.ProfilingInfo.TriState;
+import com.oracle.graal.compiler.common.type.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.graph.spi.*;
 import com.oracle.graal.nodes.*;
@@ -32,21 +34,15 @@
 /**
  * An IsNullNode will be true if the supplied value is null, and false if it is non-null.
  */
-public final class IsNullNode extends LogicNode implements Canonicalizable, LIRLowerable, Virtualizable, PiPushable {
-
-    @Input private ValueNode object;
-
-    public ValueNode object() {
-        return object;
-    }
+public final class IsNullNode extends UnaryOpLogicNode implements Canonicalizable, LIRLowerable, Virtualizable, PiPushable {
 
     /**
      * Constructs a new IsNullNode instruction.
-     * 
+     *
      * @param object the instruction producing the object to check against null
      */
     public IsNullNode(ValueNode object) {
-        this.object = object;
+        super(object);
     }
 
     @Override
@@ -63,20 +59,31 @@
 
     @Override
     public Node canonical(CanonicalizerTool tool) {
-        Constant constant = object().asConstant();
-        if (constant != null) {
-            assert constant.getKind() == Kind.Object;
-            return LogicConstantNode.forBoolean(constant.isNull(), graph());
-        }
-        if (ObjectStamp.isObjectNonNull(object.stamp())) {
-            return LogicConstantNode.contradiction(graph());
+        switch (evaluate(object())) {
+            case FALSE:
+                return LogicConstantNode.contradiction(graph());
+            case TRUE:
+                return LogicConstantNode.tautology(graph());
         }
         return this;
     }
 
     @Override
+    public TriState evaluate(ValueNode forObject) {
+        Constant constant = forObject.asConstant();
+        if (constant != null) {
+            assert constant.getKind() == Kind.Object;
+            return TriState.get(constant.isNull());
+        }
+        if (StampTool.isObjectNonNull(forObject.stamp())) {
+            return TriState.FALSE;
+        }
+        return TriState.UNKNOWN;
+    }
+
+    @Override
     public void virtualize(VirtualizerTool tool) {
-        if (tool.getObjectState(object) != null) {
+        if (tool.getObjectState(object()) != null) {
             tool.replaceWithValue(LogicConstantNode.contradiction(graph()));
         }
     }
diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/LeftShiftNode.java
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/LeftShiftNode.java	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/LeftShiftNode.java	Mon Apr 28 11:18:15 2014 +0200
@@ -23,8 +23,10 @@
 package com.oracle.graal.nodes.calc;
 
 import com.oracle.graal.api.meta.*;
+import com.oracle.graal.compiler.common.type.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.graph.spi.*;
+import com.oracle.graal.lir.gen.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.spi.*;
 import com.oracle.graal.nodes.type.*;
@@ -92,7 +94,7 @@
     }
 
     @Override
-    public void generate(NodeLIRBuilderTool gen) {
-        gen.setResult(this, gen.getLIRGeneratorTool().emitShl(gen.operand(x()), gen.operand(y())));
+    public void generate(NodeMappableLIRBuilder builder, ArithmeticLIRGenerator gen) {
+        builder.setResult(this, gen.emitShl(builder.operand(x()), builder.operand(y())));
     }
 }
diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/NarrowNode.java
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/NarrowNode.java	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/NarrowNode.java	Mon Apr 28 11:18:15 2014 +0200
@@ -23,8 +23,10 @@
 package com.oracle.graal.nodes.calc;
 
 import com.oracle.graal.api.meta.*;
+import com.oracle.graal.compiler.common.type.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.graph.spi.*;
+import com.oracle.graal.lir.gen.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.extended.*;
 import com.oracle.graal.nodes.spi.*;
@@ -50,13 +52,7 @@
 
     @Override
     public Constant reverse(Constant input) {
-        IntegerStamp stamp = (IntegerStamp) stamp();
-        long result;
-        if (stamp.isUnsigned()) {
-            result = ZeroExtendNode.zeroExtend(input.asLong(), getResultBits());
-        } else {
-            result = SignExtendNode.signExtend(input.asLong(), getResultBits());
-        }
+        long result = SignExtendNode.signExtend(input.asLong(), getResultBits());
         return Constant.forPrimitiveInt(getInputBits(), result);
     }
 
@@ -110,8 +106,8 @@
     }
 
     @Override
-    public void generate(NodeLIRBuilderTool gen) {
-        gen.setResult(this, gen.getLIRGeneratorTool().emitNarrow(gen.operand(getInput()), getResultBits()));
+    public void generate(NodeMappableLIRBuilder builder, ArithmeticLIRGenerator gen) {
+        builder.setResult(this, gen.emitNarrow(builder.operand(getInput()), getResultBits()));
     }
 
     @Override
diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/NegateNode.java
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/NegateNode.java	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/NegateNode.java	Mon Apr 28 11:18:15 2014 +0200
@@ -23,8 +23,10 @@
 package com.oracle.graal.nodes.calc;
 
 import com.oracle.graal.api.meta.*;
+import com.oracle.graal.compiler.common.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.graph.spi.*;
+import com.oracle.graal.lir.gen.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.spi.*;
 import com.oracle.graal.nodes.type.*;
@@ -88,7 +90,7 @@
     }
 
     @Override
-    public void generate(NodeLIRBuilderTool gen) {
-        gen.setResult(this, gen.getLIRGeneratorTool().emitNegate(gen.operand(x())));
+    public void generate(NodeMappableLIRBuilder builder, ArithmeticLIRGenerator gen) {
+        builder.setResult(this, gen.emitNegate(builder.operand(x())));
     }
 }
diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/NormalizeCompareNode.java
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/NormalizeCompareNode.java	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/NormalizeCompareNode.java	Mon Apr 28 11:18:15 2014 +0200
@@ -23,9 +23,9 @@
 package com.oracle.graal.nodes.calc;
 
 import com.oracle.graal.api.meta.*;
+import com.oracle.graal.compiler.common.type.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.spi.*;
-import com.oracle.graal.nodes.type.*;
 
 /**
  * Returns -1, 0, or 1 if either x < y, x == y, or x > y. If the comparison is undecided (one
diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/NotNode.java
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/NotNode.java	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/NotNode.java	Mon Apr 28 11:18:15 2014 +0200
@@ -23,8 +23,10 @@
 package com.oracle.graal.nodes.calc;
 
 import com.oracle.graal.api.meta.*;
+import com.oracle.graal.compiler.common.type.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.graph.spi.*;
+import com.oracle.graal.lir.gen.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.spi.*;
 import com.oracle.graal.nodes.type.*;
@@ -73,7 +75,7 @@
     }
 
     @Override
-    public void generate(NodeLIRBuilderTool gen) {
-        gen.setResult(this, gen.getLIRGeneratorTool().emitNot(gen.operand(x())));
+    public void generate(NodeMappableLIRBuilder builder, ArithmeticLIRGenerator gen) {
+        builder.setResult(this, gen.emitNot(builder.operand(x())));
     }
 }
diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/ObjectEqualsNode.java
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/ObjectEqualsNode.java	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/ObjectEqualsNode.java	Mon Apr 28 11:18:15 2014 +0200
@@ -23,18 +23,21 @@
 package com.oracle.graal.nodes.calc;
 
 import com.oracle.graal.api.meta.*;
+import com.oracle.graal.api.meta.ProfilingInfo.*;
+import com.oracle.graal.compiler.common.calc.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.graph.spi.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.spi.*;
 import com.oracle.graal.nodes.type.*;
+import com.oracle.graal.nodes.util.*;
 
 @NodeInfo(shortName = "==")
 public final class ObjectEqualsNode extends CompareNode implements Virtualizable {
 
     /**
      * Constructs a new object equality comparison node.
-     * 
+     *
      * @param x the instruction producing the first input to the instruction
      * @param y the instruction that produces the second input to this instruction
      */
@@ -55,21 +58,28 @@
     }
 
     @Override
-    public Node canonical(CanonicalizerTool tool) {
-        if (x() == y()) {
-            return LogicConstantNode.tautology(graph());
+    public TriState evaluate(ConstantReflectionProvider constantReflection, ValueNode forX, ValueNode forY) {
+        if (GraphUtil.unproxify(forX) == GraphUtil.unproxify(forY)) {
+            return TriState.TRUE;
+        } else if (forX.stamp().alwaysDistinct(forY.stamp())) {
+            return TriState.FALSE;
+        } else {
+            return super.evaluate(constantReflection, forX, forY);
         }
+    }
 
-        if (ObjectStamp.isObjectAlwaysNull(x())) {
+    @Override
+    public Node canonical(CanonicalizerTool tool) {
+        Node result = super.canonical(tool);
+        if (result != this) {
+            return result;
+        }
+        if (StampTool.isObjectAlwaysNull(x())) {
             return graph().unique(new IsNullNode(y()));
-        } else if (ObjectStamp.isObjectAlwaysNull(y())) {
+        } else if (StampTool.isObjectAlwaysNull(y())) {
             return graph().unique(new IsNullNode(x()));
         }
-        if (x().stamp().alwaysDistinct(y().stamp())) {
-            return LogicConstantNode.contradiction(graph());
-        }
-
-        return super.canonical(tool);
+        return this;
     }
 
     private void virtualizeNonVirtualComparison(State state, ValueNode other, VirtualizerTool tool) {
diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/OrNode.java
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/OrNode.java	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/OrNode.java	Mon Apr 28 11:18:15 2014 +0200
@@ -23,8 +23,10 @@
 package com.oracle.graal.nodes.calc;
 
 import com.oracle.graal.api.meta.*;
+import com.oracle.graal.compiler.common.type.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.graph.spi.*;
+import com.oracle.graal.lir.gen.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.extended.*;
 import com.oracle.graal.nodes.spi.*;
@@ -73,8 +75,8 @@
     }
 
     @Override
-    public void generate(NodeLIRBuilderTool gen) {
-        gen.setResult(this, gen.getLIRGeneratorTool().emitOr(gen.operand(x()), gen.operand(y())));
+    public void generate(NodeMappableLIRBuilder builder, ArithmeticLIRGenerator gen) {
+        builder.setResult(this, gen.emitOr(builder.operand(x()), builder.operand(y())));
     }
 
     @Override
diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/ReinterpretNode.java
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/ReinterpretNode.java	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/ReinterpretNode.java	Mon Apr 28 11:18:15 2014 +0200
@@ -23,12 +23,14 @@
 package com.oracle.graal.nodes.calc;
 
 import com.oracle.graal.api.meta.*;
+import com.oracle.graal.compiler.common.*;
+import com.oracle.graal.compiler.common.type.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.graph.spi.*;
+import com.oracle.graal.lir.gen.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.extended.*;
 import com.oracle.graal.nodes.spi.*;
-import com.oracle.graal.nodes.type.*;
 
 /**
  * The {@code ReinterpretNode} class represents a reinterpreting conversion that changes the stamp
@@ -102,9 +104,9 @@
     }
 
     @Override
-    public void generate(NodeLIRBuilderTool gen) {
-        PlatformKind kind = gen.getLIRGeneratorTool().getPlatformKind(stamp());
-        gen.setResult(this, gen.getLIRGeneratorTool().emitReinterpret(kind, gen.operand(value())));
+    public void generate(NodeMappableLIRBuilder builder, ArithmeticLIRGenerator gen) {
+        PlatformKind kind = gen.getPlatformKind(stamp());
+        builder.setResult(this, gen.emitReinterpret(kind, builder.operand(value())));
     }
 
     @Override
diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/RightShiftNode.java
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/RightShiftNode.java	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/RightShiftNode.java	Mon Apr 28 11:18:15 2014 +0200
@@ -23,11 +23,12 @@
 package com.oracle.graal.nodes.calc;
 
 import com.oracle.graal.api.meta.*;
+import com.oracle.graal.compiler.common.type.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.graph.spi.*;
+import com.oracle.graal.lir.gen.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.spi.*;
-import com.oracle.graal.nodes.type.*;
 
 @NodeInfo(shortName = ">>")
 public final class RightShiftNode extends ShiftNode implements Canonicalizable {
@@ -98,7 +99,7 @@
     }
 
     @Override
-    public void generate(NodeLIRBuilderTool gen) {
-        gen.setResult(this, gen.getLIRGeneratorTool().emitShr(gen.operand(x()), gen.operand(y())));
+    public void generate(NodeMappableLIRBuilder builder, ArithmeticLIRGenerator gen) {
+        builder.setResult(this, gen.emitShr(builder.operand(x()), builder.operand(y())));
     }
 }
diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/ShiftNode.java
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/ShiftNode.java	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/ShiftNode.java	Mon Apr 28 11:18:15 2014 +0200
@@ -23,9 +23,9 @@
 package com.oracle.graal.nodes.calc;
 
 import com.oracle.graal.api.meta.*;
+import com.oracle.graal.compiler.common.type.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.spi.*;
-import com.oracle.graal.nodes.type.*;
 
 /**
  * The {@code ShiftOp} class represents shift operations.
diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/SignExtendNode.java
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/SignExtendNode.java	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/SignExtendNode.java	Mon Apr 28 11:18:15 2014 +0200
@@ -23,8 +23,10 @@
 package com.oracle.graal.nodes.calc;
 
 import com.oracle.graal.api.meta.*;
+import com.oracle.graal.compiler.common.type.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.graph.spi.*;
+import com.oracle.graal.lir.gen.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.extended.*;
 import com.oracle.graal.nodes.spi.*;
@@ -105,13 +107,13 @@
     }
 
     @Override
-    public void generate(NodeLIRBuilderTool gen) {
-        gen.setResult(this, gen.getLIRGeneratorTool().emitSignExtend(gen.operand(getInput()), getInputBits(), getResultBits()));
+    public void generate(NodeMappableLIRBuilder builder, ArithmeticLIRGenerator gen) {
+        builder.setResult(this, gen.emitSignExtend(builder.operand(getInput()), getInputBits(), getResultBits()));
     }
 
     @Override
     public boolean generate(MemoryArithmeticLIRLowerer gen, Access access) {
-        Value result = gen.emitSignExtendMemory(access, access.accessLocation().getValueKind().getBitCount(), getResultBits());
+        Value result = gen.emitSignExtendMemory(access, getInputBits(), getResultBits());
         if (result != null) {
             gen.setResult(this, result);
         }
diff -r 3dde8d8c95b8 -r 40d0022115ee 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	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/UnsignedDivNode.java	Mon Apr 28 11:18:15 2014 +0200
@@ -24,11 +24,11 @@
 
 import com.oracle.graal.api.code.*;
 import com.oracle.graal.api.meta.*;
+import com.oracle.graal.compiler.common.type.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.graph.spi.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.spi.*;
-import com.oracle.graal.nodes.type.*;
 
 @NodeInfo(shortName = "|/|")
 public class UnsignedDivNode extends FixedBinaryNode implements Canonicalizable, Lowerable, LIRLowerable {
@@ -72,7 +72,7 @@
 
     @Override
     public void generate(NodeLIRBuilderTool gen) {
-        gen.setResult(this, gen.getLIRGeneratorTool().emitUDiv(gen.operand(x()), gen.operand(y()), this));
+        gen.setResult(this, gen.getLIRGeneratorTool().emitUDiv(gen.operand(x()), gen.operand(y()), gen.state(this)));
     }
 
     @Override
diff -r 3dde8d8c95b8 -r 40d0022115ee 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	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/UnsignedRemNode.java	Mon Apr 28 11:18:15 2014 +0200
@@ -24,11 +24,11 @@
 
 import com.oracle.graal.api.code.*;
 import com.oracle.graal.api.meta.*;
+import com.oracle.graal.compiler.common.type.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.graph.spi.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.spi.*;
-import com.oracle.graal.nodes.type.*;
 
 @NodeInfo(shortName = "|%|")
 public class UnsignedRemNode extends FixedBinaryNode implements Canonicalizable, Lowerable, LIRLowerable {
@@ -71,7 +71,7 @@
 
     @Override
     public void generate(NodeLIRBuilderTool gen) {
-        gen.setResult(this, gen.getLIRGeneratorTool().emitURem(gen.operand(x()), gen.operand(y()), this));
+        gen.setResult(this, gen.getLIRGeneratorTool().emitURem(gen.operand(x()), gen.operand(y()), gen.state(this)));
     }
 
     @Override
diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/UnsignedRightShiftNode.java
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/UnsignedRightShiftNode.java	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/UnsignedRightShiftNode.java	Mon Apr 28 11:18:15 2014 +0200
@@ -23,8 +23,10 @@
 package com.oracle.graal.nodes.calc;
 
 import com.oracle.graal.api.meta.*;
+import com.oracle.graal.compiler.common.type.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.graph.spi.*;
+import com.oracle.graal.lir.gen.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.spi.*;
 import com.oracle.graal.nodes.type.*;
@@ -92,7 +94,7 @@
     }
 
     @Override
-    public void generate(NodeLIRBuilderTool gen) {
-        gen.setResult(this, gen.getLIRGeneratorTool().emitUShr(gen.operand(x()), gen.operand(y())));
+    public void generate(NodeMappableLIRBuilder builder, ArithmeticLIRGenerator gen) {
+        builder.setResult(this, gen.emitUShr(builder.operand(x()), builder.operand(y())));
     }
 }
diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/XorNode.java
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/XorNode.java	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/XorNode.java	Mon Apr 28 11:18:15 2014 +0200
@@ -23,8 +23,10 @@
 package com.oracle.graal.nodes.calc;
 
 import com.oracle.graal.api.meta.*;
+import com.oracle.graal.compiler.common.type.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.graph.spi.*;
+import com.oracle.graal.lir.gen.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.extended.*;
 import com.oracle.graal.nodes.spi.*;
@@ -72,8 +74,8 @@
     }
 
     @Override
-    public void generate(NodeLIRBuilderTool gen) {
-        gen.setResult(this, gen.getLIRGeneratorTool().emitXor(gen.operand(x()), gen.operand(y())));
+    public void generate(NodeMappableLIRBuilder builder, ArithmeticLIRGenerator gen) {
+        builder.setResult(this, gen.emitXor(builder.operand(x()), builder.operand(y())));
     }
 
     @Override
diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/ZeroExtendNode.java
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/ZeroExtendNode.java	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/ZeroExtendNode.java	Mon Apr 28 11:18:15 2014 +0200
@@ -23,8 +23,10 @@
 package com.oracle.graal.nodes.calc;
 
 import com.oracle.graal.api.meta.*;
+import com.oracle.graal.compiler.common.type.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.graph.spi.*;
+import com.oracle.graal.lir.gen.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.extended.*;
 import com.oracle.graal.nodes.spi.*;
@@ -98,8 +100,8 @@
     }
 
     @Override
-    public void generate(NodeLIRBuilderTool gen) {
-        gen.setResult(this, gen.getLIRGeneratorTool().emitZeroExtend(gen.operand(getInput()), getInputBits(), getResultBits()));
+    public void generate(NodeMappableLIRBuilder builder, ArithmeticLIRGenerator gen) {
+        builder.setResult(this, gen.emitZeroExtend(builder.operand(getInput()), getInputBits(), getResultBits()));
     }
 
     @Override
diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/cfg/AbstractBlock.java
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/cfg/AbstractBlock.java	Fri Apr 25 16:21:07 2014 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,58 +0,0 @@
-/*
- * Copyright (c) 2014, 2014, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.graal.nodes.cfg;
-
-import java.util.*;
-
-public interface AbstractBlock> {
-
-    int getId();
-
-    Loop getLoop();
-
-    int getLoopDepth();
-
-    boolean isLoopHeader();
-
-    boolean isLoopEnd();
-
-    boolean isExceptionEntry();
-
-    List getPredecessors();
-
-    int getPredecessorCount();
-
-    List getSuccessors();
-
-    int getSuccessorCount();
-
-    int getLinearScanNumber();
-
-    void setLinearScanNumber(int linearScanNumber);
-
-    boolean isAligned();
-
-    void setAlign(boolean align);
-
-    T getDominator();
-}
diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/cfg/AbstractBlockBase.java
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/cfg/AbstractBlockBase.java	Fri Apr 25 16:21:07 2014 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,92 +0,0 @@
-/*
- * Copyright (c) 2009, 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.nodes.cfg;
-
-import java.util.*;
-
-public abstract class AbstractBlockBase> implements AbstractBlock {
-
-    protected int id;
-
-    protected List predecessors;
-    protected List successors;
-
-    protected T dominator;
-
-    private boolean align;
-    private int linearScanNumber;
-
-    protected AbstractBlockBase() {
-        this.id = ControlFlowGraph.BLOCK_ID_INITIAL;
-        this.linearScanNumber = -1;
-    }
-
-    public int getId() {
-        return id;
-    }
-
-    public void setId(int id) {
-        this.id = id;
-    }
-
-    public List getPredecessors() {
-        return predecessors;
-    }
-
-    public List getSuccessors() {
-        return successors;
-    }
-
-    public T getDominator() {
-        return dominator;
-    }
-
-    @Override
-    public String toString() {
-        return "B" + id;
-    }
-
-    public int getPredecessorCount() {
-        return getPredecessors().size();
-    }
-
-    public int getSuccessorCount() {
-        return getSuccessors().size();
-    }
-
-    public int getLinearScanNumber() {
-        return linearScanNumber;
-    }
-
-    public void setLinearScanNumber(int linearScanNumber) {
-        this.linearScanNumber = linearScanNumber;
-    }
-
-    public boolean isAligned() {
-        return align;
-    }
-
-    public void setAlign(boolean align) {
-        this.align = align;
-    }
-}
diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/cfg/AbstractControlFlowGraph.java
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/cfg/AbstractControlFlowGraph.java	Fri Apr 25 16:21:07 2014 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,32 +0,0 @@
-/*
- * Copyright (c) 2014, 2014, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.graal.nodes.cfg;
-
-public interface AbstractControlFlowGraph> {
-
-    T[] getBlocks();
-
-    Loop[] getLoops();
-
-    T getStartBlock();
-}
diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/cfg/Block.java
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/cfg/Block.java	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/cfg/Block.java	Mon Apr 28 11:18:15 2014 +0200
@@ -24,24 +24,25 @@
 
 import java.util.*;
 
+import com.oracle.graal.compiler.common.cfg.*;
+import com.oracle.graal.graph.*;
 import com.oracle.graal.nodes.*;
-import com.oracle.graal.nodes.java.*;
 
 public final class Block extends AbstractBlockBase {
 
-    protected final AbstractBeginNode beginNode;
+    protected final BeginNode beginNode;
 
     protected FixedNode endNode;
-    protected Loop loop;
+    protected Loop loop;
 
     protected List dominated;
     protected Block postdominator;
 
-    protected Block(AbstractBeginNode node) {
+    protected Block(BeginNode node) {
         this.beginNode = node;
     }
 
-    public AbstractBeginNode getBeginNode() {
+    public BeginNode getBeginNode() {
         return beginNode;
     }
 
@@ -49,7 +50,7 @@
         return endNode;
     }
 
-    public Loop getLoop() {
+    public Loop getLoop() {
         return loop;
     }
 
@@ -66,15 +67,16 @@
     }
 
     public boolean isExceptionEntry() {
-        return getBeginNode() instanceof ExceptionObjectNode;
+        Node predecessor = getBeginNode().predecessor();
+        return predecessor != null && predecessor instanceof InvokeWithExceptionNode && getBeginNode() == ((InvokeWithExceptionNode) predecessor).exceptionEdge();
     }
 
     public Block getFirstPredecessor() {
-        return predecessors.get(0);
+        return getPredecessors().get(0);
     }
 
     public Block getFirstSuccessor() {
-        return successors.get(0);
+        return getSuccessors().get(0);
     }
 
     public Block getEarliestPostDominated() {
@@ -122,7 +124,7 @@
             } else {
                 cur = ((FixedWithNextNode) cur).next();
             }
-            assert !(cur instanceof AbstractBeginNode);
+            assert !(cur instanceof BeginNode);
             return result;
         }
 
@@ -167,10 +169,10 @@
         if (block == this) {
             return true;
         }
-        if (dominator == null) {
+        if (getDominator() == null) {
             return false;
         }
-        return dominator.isDominatedBy(block);
+        return getDominator().isDominatedBy(block);
     }
 
 }
diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/cfg/BlockMap.java
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/cfg/BlockMap.java	Fri Apr 25 16:21:07 2014 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,41 +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.nodes.cfg;
-
-public class BlockMap {
-
-    private final T[] data;
-
-    @SuppressWarnings("unchecked")
-    public BlockMap(AbstractControlFlowGraph cfg) {
-        data = (T[]) new Object[cfg.getBlocks().length];
-    }
-
-    public T get(AbstractBlock block) {
-        return data[block.getId()];
-    }
-
-    public void put(AbstractBlock block, T value) {
-        data[block.getId()] = value;
-    }
-}
diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/cfg/BlocksToDoubles.java
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/cfg/BlocksToDoubles.java	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/cfg/BlocksToDoubles.java	Mon Apr 28 11:18:15 2014 +0200
@@ -24,6 +24,7 @@
 
 import java.util.*;
 
+import com.oracle.graal.compiler.common.cfg.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.util.*;
 
diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/cfg/CFGVerifier.java
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/cfg/CFGVerifier.java	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/cfg/CFGVerifier.java	Mon Apr 28 11:18:15 2014 +0200
@@ -24,6 +24,8 @@
 
 import java.util.*;
 
+import com.oracle.graal.compiler.common.cfg.*;
+
 public class CFGVerifier {
 
     public static boolean verify(ControlFlowGraph cfg) {
@@ -84,13 +86,13 @@
         }
 
         if (cfg.getLoops() != null) {
-            for (Loop loop : cfg.getLoops()) {
+            for (Loop loop : cfg.getLoops()) {
                 assert loop.header.isLoopHeader();
 
                 for (Block block : loop.blocks) {
                     assert block.getId() >= loop.header.getId();
 
-                    Loop blockLoop = block.getLoop();
+                    Loop blockLoop = block.getLoop();
                     while (blockLoop != loop) {
                         assert blockLoop != null;
                         blockLoop = blockLoop.parent;
@@ -109,7 +111,7 @@
                 for (Block block : loop.exits) {
                     assert block.getId() >= loop.header.getId();
 
-                    Loop blockLoop = block.getLoop();
+                    Loop blockLoop = block.getLoop();
                     while (blockLoop != null) {
                         blockLoop = blockLoop.parent;
                         assert blockLoop != loop;
diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/cfg/ControlFlowGraph.java
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/cfg/ControlFlowGraph.java	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/cfg/ControlFlowGraph.java	Mon Apr 28 11:18:15 2014 +0200
@@ -24,6 +24,8 @@
 
 import java.util.*;
 
+import com.oracle.graal.compiler.common.*;
+import com.oracle.graal.compiler.common.cfg.*;
 import com.oracle.graal.debug.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.nodes.*;
@@ -34,7 +36,7 @@
 
     private final NodeMap nodeToBlock;
     private Block[] reversePostOrder;
-    private Loop[] loops;
+    private List> loops;
 
     public static ControlFlowGraph compute(StructuredGraph graph, boolean connectBlocks, boolean computeLoops, boolean computeDominators, boolean computePostdominators) {
         ControlFlowGraph cfg = new ControlFlowGraph(graph);
@@ -106,7 +108,7 @@
         return nodeToBlock.get(node);
     }
 
-    public Loop[] getLoops() {
+    public List> getLoops() {
         return loops;
     }
 
@@ -117,15 +119,12 @@
         }
     }
 
-    protected static final int BLOCK_ID_INITIAL = -1;
-    protected static final int BLOCK_ID_VISITED = -2;
-
     private void identifyBlock(Block block) {
         Node cur = block.getBeginNode();
         Node last;
 
         // assign proxies of a loop exit to this block
-        if (cur instanceof AbstractBeginNode) {
+        if (cur instanceof BeginNode) {
             for (Node usage : cur.usages()) {
                 if (usage instanceof ProxyNode) {
                     nodeToBlock.set(usage, block);
@@ -146,7 +145,7 @@
 
             last = cur;
             cur = cur.successors().first();
-        } while (cur != null && !(cur instanceof AbstractBeginNode));
+        } while (cur != null && !(cur instanceof BeginNode));
 
         block.endNode = (FixedNode) last;
     }
@@ -154,7 +153,7 @@
     private void identifyBlocks() {
         // Find all block headers
         int numBlocks = 0;
-        for (AbstractBeginNode begin : graph.getNodes(AbstractBeginNode.class)) {
+        for (BeginNode begin : graph.getNodes(BeginNode.class)) {
             Block block = new Block(begin);
             numBlocks++;
             identifyBlock(block);
@@ -167,16 +166,16 @@
 
         do {
             Block block = stack.get(stack.size() - 1);
-            if (block.id == BLOCK_ID_INITIAL) {
+            if (block.getId() == BLOCK_ID_INITIAL) {
                 // First time we see this block: push all successors.
                 for (Node suxNode : block.getEndNode().cfgSuccessors()) {
                     Block suxBlock = blockFor(suxNode);
-                    if (suxBlock.id == BLOCK_ID_INITIAL) {
+                    if (suxBlock.getId() == BLOCK_ID_INITIAL) {
                         stack.add(suxBlock);
                     }
                 }
-                block.id = BLOCK_ID_VISITED;
-            } else if (block.id == BLOCK_ID_VISITED) {
+                block.setId(BLOCK_ID_VISITED);
+            } else if (block.getId() == BLOCK_ID_VISITED) {
                 // Second time we see this block: All successors have been processed, so add block
                 // to postorder list.
                 stack.remove(stack.size() - 1);
@@ -192,7 +191,7 @@
         reversePostOrder = new Block[numBlocks];
         for (int i = 0; i < numBlocks; i++) {
             Block block = postOrder.get(numBlocks - i - 1);
-            block.id = i;
+            block.setId(i);
             reversePostOrder[i] = block;
         }
     }
@@ -203,42 +202,42 @@
             List predecessors = new ArrayList<>(4);
             for (Node predNode : block.getBeginNode().cfgPredecessors()) {
                 Block predBlock = nodeToBlock.get(predNode);
-                if (predBlock.id >= 0) {
+                if (predBlock.getId() >= 0) {
                     predecessors.add(predBlock);
                 }
             }
             if (block.getBeginNode() instanceof LoopBeginNode) {
                 for (LoopEndNode predNode : ((LoopBeginNode) block.getBeginNode()).orderedLoopEnds()) {
                     Block predBlock = nodeToBlock.get(predNode);
-                    if (predBlock.id >= 0) {
+                    if (predBlock.getId() >= 0) {
                         predecessors.add(predBlock);
                     }
                 }
             }
-            block.predecessors = predecessors;
+            block.setPredecessors(predecessors);
 
             List successors = new ArrayList<>(4);
             for (Node suxNode : block.getEndNode().cfgSuccessors()) {
                 Block suxBlock = nodeToBlock.get(suxNode);
-                assert suxBlock.id >= 0;
+                assert suxBlock.getId() >= 0;
                 successors.add(suxBlock);
             }
             if (block.getEndNode() instanceof LoopEndNode) {
                 Block suxBlock = nodeToBlock.get(((LoopEndNode) block.getEndNode()).loopBegin());
-                assert suxBlock.id >= 0;
+                assert suxBlock.getId() >= 0;
                 successors.add(suxBlock);
             }
-            block.successors = successors;
+            block.setSuccessors(successors);
         }
     }
 
     private void computeLoopInformation() {
-        ArrayList loopsList = new ArrayList<>();
+        loops = new ArrayList<>();
         for (Block block : reversePostOrder) {
             Node beginNode = block.getBeginNode();
             if (beginNode instanceof LoopBeginNode) {
-                Loop loop = new Loop(block.getLoop(), loopsList.size(), block);
-                loopsList.add(loop);
+                Loop loop = new HIRLoop(block.getLoop(), loops.size(), block);
+                loops.add(loop);
 
                 LoopBeginNode loopBegin = (LoopBeginNode) beginNode;
                 for (LoopEndNode end : loopBegin.loopEnds()) {
@@ -256,7 +255,7 @@
                 for (Block b : loop.blocks) {
                     for (Block sux : b.getSuccessors()) {
                         if (sux.loop != loop) {
-                            AbstractBeginNode begin = sux.getBeginNode();
+                            BeginNode begin = sux.getBeginNode();
                             if (!(begin instanceof LoopExitNode && ((LoopExitNode) begin).loopBegin() == loopBegin)) {
                                 Debug.log("Unexpected loop exit with %s, including whole branch in the loop", sux);
                                 unexpected.add(sux);
@@ -269,10 +268,9 @@
                 }
             }
         }
-        loops = loopsList.toArray(new Loop[loopsList.size()]);
     }
 
-    private static void addBranchToLoop(Loop l, Block b) {
+    private static void addBranchToLoop(Loop l, Block b) {
         if (l.blocks.contains(b)) {
             return;
         }
@@ -283,7 +281,7 @@
         }
     }
 
-    private static void computeLoopBlocks(Block block, Loop loop) {
+    private static void computeLoopBlocks(Block block, Loop loop) {
         if (block.getLoop() == loop) {
             return;
         }
@@ -316,22 +314,22 @@
     }
 
     private static void setDominator(Block block, Block dominator) {
-        block.dominator = dominator;
+        block.setDominator(dominator);
         if (dominator.dominated == null) {
             dominator.dominated = new ArrayList<>();
         }
         dominator.dominated.add(block);
     }
 
-    public static Block commonDominator(Block a, Block b) {
+    public static > T commonDominator(T a, T b) {
         if (a == null) {
             return b;
         }
         if (b == null) {
             return a;
         }
-        Block iterA = a;
-        Block iterB = b;
+        T iterA = a;
+        T iterB = b;
         while (iterA != iterB) {
             if (iterA.getId() > iterB.getId()) {
                 iterA = iterA.getDominator();
diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/cfg/HIRLoop.java
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/cfg/HIRLoop.java	Mon Apr 28 11:18:15 2014 +0200
@@ -0,0 +1,38 @@
+/*
+ * Copyright (c) 2014, 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.graal.nodes.cfg;
+
+import com.oracle.graal.compiler.common.cfg.*;
+import com.oracle.graal.nodes.*;
+
+public class HIRLoop extends Loop {
+
+    protected HIRLoop(Loop parent, int index, Block header) {
+        super(parent, index, header);
+    }
+
+    @Override
+    public long numBackedges() {
+        return ((LoopBeginNode) header.getBeginNode()).loopEnds().count();
+    }
+}
diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/cfg/Loop.java
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/cfg/Loop.java	Fri Apr 25 16:21:07 2014 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,63 +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.nodes.cfg;
-
-import java.util.*;
-
-import com.oracle.graal.nodes.*;
-
-public class Loop {
-
-    public final Loop parent;
-    public final List children;
-
-    public final int depth;
-    public final int index;
-    public final Block header;
-    public final List blocks;
-    public final List exits;
-
-    protected Loop(Loop parent, int index, Block header) {
-        this.parent = parent;
-        if (parent != null) {
-            this.depth = parent.depth + 1;
-            parent.children.add(this);
-        } else {
-            this.depth = 1;
-        }
-        this.index = index;
-        this.header = header;
-        this.blocks = new ArrayList<>();
-        this.children = new ArrayList<>();
-        this.exits = new ArrayList<>();
-    }
-
-    @Override
-    public String toString() {
-        return "loop " + index + " depth " + depth + (parent != null ? " outer " + parent.index : "");
-    }
-
-    public LoopBeginNode loopBegin() {
-        return (LoopBeginNode) header.getBeginNode();
-    }
-}
diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/debug/DynamicCounterNode.java
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/debug/DynamicCounterNode.java	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/debug/DynamicCounterNode.java	Mon Apr 28 11:18:15 2014 +0200
@@ -22,15 +22,15 @@
  */
 package com.oracle.graal.nodes.debug;
 
+import com.oracle.graal.compiler.common.type.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.spi.*;
-import com.oracle.graal.nodes.type.*;
 
 /**
  * This node can be used to add a counter to the code that will estimate the dynamic number of calls
  * by adding an increment to the compiled code. This should of course only be used for
  * debugging/testing purposes.
- * 
+ *
  * A unique counter will be created for each unique name passed to the constructor. Depending on the
  * value of withContext, the name of the root method is added to the counter's name.
  */
diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/AbstractWriteNode.java
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/AbstractWriteNode.java	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/AbstractWriteNode.java	Mon Apr 28 11:18:15 2014 +0200
@@ -23,9 +23,9 @@
 package com.oracle.graal.nodes.extended;
 
 import com.oracle.graal.api.meta.*;
+import com.oracle.graal.compiler.common.type.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.nodes.*;
-import com.oracle.graal.nodes.type.*;
 
 @NodeInfo(allowedUsageTypes = {InputType.Memory})
 public abstract class AbstractWriteNode extends FixedAccessNode implements StateSplit, MemoryCheckpoint.Single, MemoryAccess, GuardingNode {
diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/AddLocationNode.java
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/AddLocationNode.java	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/AddLocationNode.java	Mon Apr 28 11:18:15 2014 +0200
@@ -23,12 +23,13 @@
 package com.oracle.graal.nodes.extended;
 
 import com.oracle.graal.api.meta.*;
+import com.oracle.graal.compiler.common.type.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.graph.spi.*;
+import com.oracle.graal.lir.gen.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.calc.*;
 import com.oracle.graal.nodes.spi.*;
-import com.oracle.graal.nodes.type.*;
 
 /**
  * Location node that is the sum of two other location nodes. Can represent locations in the form of
@@ -37,8 +38,8 @@
 @NodeInfo(nameTemplate = "AddLoc {p#locationIdentity/s}")
 public final class AddLocationNode extends LocationNode implements Canonicalizable {
 
-    @Input private ValueNode x;
-    @Input private ValueNode y;
+    @Input(InputType.Association) private ValueNode x;
+    @Input(InputType.Association) private ValueNode y;
 
     protected LocationNode getX() {
         return (LocationNode) x;
@@ -107,9 +108,9 @@
     }
 
     @Override
-    public Value generateAddress(NodeLIRBuilderTool gen, Value base) {
-        Value xAddr = getX().generateAddress(gen, base);
-        return getY().generateAddress(gen, xAddr);
+    public Value generateAddress(NodeMappableLIRBuilder builder, LIRGeneratorTool gen, Value base) {
+        Value xAddr = getX().generateAddress(builder, gen, base);
+        return getY().generateAddress(builder, gen, xAddr);
     }
 
     @NodeIntrinsic
diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/ArrayRangeWriteNode.java
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/ArrayRangeWriteNode.java	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/ArrayRangeWriteNode.java	Mon Apr 28 11:18:15 2014 +0200
@@ -22,8 +22,8 @@
  */
 package com.oracle.graal.nodes.extended;
 
+import com.oracle.graal.compiler.common.type.*;
 import com.oracle.graal.nodes.*;
-import com.oracle.graal.nodes.type.*;
 
 /**
  * Base class for nodes that modify a range of an array.
diff -r 3dde8d8c95b8 -r 40d0022115ee 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	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/BoxNode.java	Mon Apr 28 11:18:15 2014 +0200
@@ -25,6 +25,7 @@
 import java.util.*;
 
 import com.oracle.graal.api.meta.*;
+import com.oracle.graal.compiler.common.type.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.graph.spi.*;
 import com.oracle.graal.nodes.*;
@@ -77,7 +78,7 @@
     @Override
     public void virtualize(VirtualizerTool tool) {
         ValueNode v = tool.getReplacedValue(getValue());
-        ResolvedJavaType type = ObjectStamp.typeOrNull(stamp());
+        ResolvedJavaType type = StampTool.typeOrNull(stamp());
 
         VirtualBoxingNode newVirtual = new VirtualBoxingNode(type, boxingKind);
         assert newVirtual.getFields().length == 1;
diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/BranchProbabilityNode.java
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/BranchProbabilityNode.java	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/BranchProbabilityNode.java	Mon Apr 28 11:18:15 2014 +0200
@@ -22,6 +22,8 @@
  */
 package com.oracle.graal.nodes.extended;
 
+import com.oracle.graal.compiler.common.*;
+import com.oracle.graal.compiler.common.calc.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.graph.spi.*;
 import com.oracle.graal.nodes.*;
diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/BytecodeExceptionNode.java
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/BytecodeExceptionNode.java	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/BytecodeExceptionNode.java	Mon Apr 28 11:18:15 2014 +0200
@@ -23,10 +23,10 @@
 package com.oracle.graal.nodes.extended;
 
 import com.oracle.graal.api.meta.*;
+import com.oracle.graal.compiler.common.type.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.spi.*;
-import com.oracle.graal.nodes.type.*;
 
 /**
  * A node that represents an exception thrown implicitly by a Java bytecode. It can be lowered to
diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/ComputeAddressNode.java
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/ComputeAddressNode.java	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/ComputeAddressNode.java	Mon Apr 28 11:18:15 2014 +0200
@@ -23,11 +23,11 @@
 package com.oracle.graal.nodes.extended;
 
 import com.oracle.graal.api.meta.*;
+import com.oracle.graal.compiler.common.type.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.calc.*;
 import com.oracle.graal.nodes.spi.*;
-import com.oracle.graal.nodes.type.*;
 
 public class ComputeAddressNode extends FloatingNode implements LIRLowerable {
 
@@ -50,7 +50,7 @@
 
     @Override
     public void generate(NodeLIRBuilderTool gen) {
-        Value addr = getLocation().generateAddress(gen, gen.operand(getObject()));
+        Value addr = getLocation().generateAddress(gen, gen.getLIRGeneratorTool(), gen.operand(getObject()));
         gen.setResult(this, addr);
     }
 }
diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/ConstantLocationNode.java
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/ConstantLocationNode.java	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/ConstantLocationNode.java	Mon Apr 28 11:18:15 2014 +0200
@@ -23,9 +23,10 @@
 package com.oracle.graal.nodes.extended;
 
 import com.oracle.graal.api.meta.*;
+import com.oracle.graal.compiler.common.type.*;
 import com.oracle.graal.graph.*;
+import com.oracle.graal.lir.gen.*;
 import com.oracle.graal.nodes.spi.*;
-import com.oracle.graal.nodes.type.*;
 
 /**
  * Location node that has a constant displacement. Can represent addresses of the form [base + disp]
@@ -65,7 +66,7 @@
     }
 
     @Override
-    public Value generateAddress(NodeLIRBuilderTool gen, Value base) {
-        return gen.getLIRGeneratorTool().emitAddress(base, getDisplacement(), Value.ILLEGAL, 0);
+    public Value generateAddress(NodeMappableLIRBuilder builder, LIRGeneratorTool gen, Value base) {
+        return gen.emitAddress(base, getDisplacement(), Value.ILLEGAL, 0);
     }
 }
diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/FixedAccessNode.java
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/FixedAccessNode.java	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/FixedAccessNode.java	Mon Apr 28 11:18:15 2014 +0200
@@ -22,9 +22,9 @@
  */
 package com.oracle.graal.nodes.extended;
 
+import com.oracle.graal.compiler.common.type.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.nodes.*;
-import com.oracle.graal.nodes.type.*;
 
 /**
  * Accesses a value at an memory address specified by an {@linkplain #object object} and a
diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/FixedValueAnchorNode.java
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/FixedValueAnchorNode.java	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/FixedValueAnchorNode.java	Mon Apr 28 11:18:15 2014 +0200
@@ -22,9 +22,9 @@
  */
 package com.oracle.graal.nodes.extended;
 
+import com.oracle.graal.compiler.common.type.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.spi.*;
-import com.oracle.graal.nodes.type.*;
 
 public final class FixedValueAnchorNode extends FixedWithNextNode implements LIRLowerable, ValueProxy {
 
diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/FloatableAccessNode.java
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/FloatableAccessNode.java	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/FloatableAccessNode.java	Mon Apr 28 11:18:15 2014 +0200
@@ -23,8 +23,8 @@
 package com.oracle.graal.nodes.extended;
 
 import com.oracle.graal.api.meta.*;
+import com.oracle.graal.compiler.common.type.*;
 import com.oracle.graal.nodes.*;
-import com.oracle.graal.nodes.type.*;
 
 /**
  * An {@link FixedAccessNode} that can be converted to a {@link FloatingAccessNode}.
diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/FloatingAccessNode.java
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/FloatingAccessNode.java	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/FloatingAccessNode.java	Mon Apr 28 11:18:15 2014 +0200
@@ -23,9 +23,9 @@
 package com.oracle.graal.nodes.extended;
 
 import com.oracle.graal.api.meta.*;
+import com.oracle.graal.compiler.common.type.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.nodes.*;
-import com.oracle.graal.nodes.type.*;
 
 public abstract class FloatingAccessNode extends FloatingGuardedNode implements Access, MemoryAccess {
 
diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/FloatingReadNode.java
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/FloatingReadNode.java	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/FloatingReadNode.java	Mon Apr 28 11:18:15 2014 +0200
@@ -23,11 +23,11 @@
 package com.oracle.graal.nodes.extended;
 
 import com.oracle.graal.api.meta.*;
+import com.oracle.graal.compiler.common.type.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.graph.spi.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.spi.*;
-import com.oracle.graal.nodes.type.*;
 
 /**
  * A floating read of a value from memory specified in terms of an object base and an object
@@ -61,9 +61,9 @@
 
     @Override
     public void generate(NodeLIRBuilderTool gen) {
-        Value address = location().generateAddress(gen, gen.operand(object()));
+        Value address = location().generateAddress(gen, gen.getLIRGeneratorTool(), gen.operand(object()));
         PlatformKind readKind = gen.getLIRGeneratorTool().getPlatformKind(stamp());
-        gen.setResult(this, gen.getLIRGeneratorTool().emitLoad(readKind, address, this));
+        gen.setResult(this, gen.getLIRGeneratorTool().emitLoad(readKind, address, null));
     }
 
     @Override
diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/ForeignCallNode.java
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/ForeignCallNode.java	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/ForeignCallNode.java	Mon Apr 28 11:18:15 2014 +0200
@@ -26,10 +26,10 @@
 
 import com.oracle.graal.api.code.*;
 import com.oracle.graal.api.meta.*;
+import com.oracle.graal.compiler.common.type.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.spi.*;
-import com.oracle.graal.nodes.type.*;
 
 /**
  * Node for a {@linkplain ForeignCallDescriptor foreign} call.
@@ -94,7 +94,7 @@
     public void generate(NodeLIRBuilderTool gen) {
         ForeignCallLinkage linkage = gen.getLIRGeneratorTool().getForeignCalls().lookupForeignCall(descriptor);
         Value[] operands = operands(gen);
-        Value result = gen.getLIRGeneratorTool().emitForeignCall(linkage, this, operands);
+        Value result = gen.getLIRGeneratorTool().emitForeignCall(linkage, gen.state(this), operands);
         if (result != null) {
             gen.setResult(this, result);
         }
diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/GuardedNode.java
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/GuardedNode.java	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/GuardedNode.java	Mon Apr 28 11:18:15 2014 +0200
@@ -22,12 +22,13 @@
  */
 package com.oracle.graal.nodes.extended;
 
+import com.oracle.graal.graph.*;
 import com.oracle.graal.nodes.*;
 
 /**
  * A node that may be guarded by a {@linkplain GuardingNode guarding node}.
  */
-public interface GuardedNode {
+public interface GuardedNode extends NodeInterface {
 
     GuardingNode getGuard();
 
diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/IndexedLocationNode.java
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/IndexedLocationNode.java	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/IndexedLocationNode.java	Mon Apr 28 11:18:15 2014 +0200
@@ -23,11 +23,12 @@
 package com.oracle.graal.nodes.extended;
 
 import com.oracle.graal.api.meta.*;
+import com.oracle.graal.compiler.common.type.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.graph.spi.*;
+import com.oracle.graal.lir.gen.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.spi.*;
-import com.oracle.graal.nodes.type.*;
 
 /**
  * Location node that has a displacement and a scaled index. Can represent locations in the form of
@@ -96,7 +97,7 @@
     }
 
     @Override
-    public Value generateAddress(NodeLIRBuilderTool gen, Value base) {
-        return gen.getLIRGeneratorTool().emitAddress(base, displacement, gen.operand(getIndex()), getIndexScaling());
+    public Value generateAddress(NodeMappableLIRBuilder builder, LIRGeneratorTool gen, Value base) {
+        return gen.emitAddress(base, displacement, builder.operand(getIndex()), getIndexScaling());
     }
 }
diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/IntegerSwitchNode.java
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/IntegerSwitchNode.java	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/IntegerSwitchNode.java	Mon Apr 28 11:18:15 2014 +0200
@@ -25,10 +25,10 @@
 import java.util.*;
 
 import com.oracle.graal.api.meta.*;
+import com.oracle.graal.compiler.common.type.*;
 import com.oracle.graal.graph.spi.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.spi.*;
-import com.oracle.graal.nodes.type.*;
 import com.oracle.graal.nodes.util.*;
 
 /**
@@ -49,7 +49,7 @@
      * @param keyProbabilities the probabilities of the keys
      * @param keySuccessors the successor index for each key
      */
-    public IntegerSwitchNode(ValueNode value, AbstractBeginNode[] successors, int[] keys, double[] keyProbabilities, int[] keySuccessors) {
+    public IntegerSwitchNode(ValueNode value, BeginNode[] successors, int[] keys, double[] keyProbabilities, int[] keySuccessors) {
         super(value, successors, keySuccessors, keyProbabilities);
         assert keySuccessors.length == keys.length + 1;
         assert keySuccessors.length == keyProbabilities.length;
@@ -76,7 +76,7 @@
      * @param keySuccessors the successor index for each key
      */
     public IntegerSwitchNode(ValueNode value, int successorCount, int[] keys, double[] keyProbabilities, int[] keySuccessors) {
-        this(value, new AbstractBeginNode[successorCount], keys, keyProbabilities, keySuccessors);
+        this(value, new BeginNode[successorCount], keys, keyProbabilities, keySuccessors);
     }
 
     @Override
@@ -139,7 +139,7 @@
                     tool.addToWorkList(defaultSuccessor());
                     graph().removeSplitPropagate(this, defaultSuccessor());
                 } else if (validKeys != keys.length) {
-                    ArrayList newSuccessors = new ArrayList<>(blockSuccessorCount());
+                    ArrayList newSuccessors = new ArrayList<>(blockSuccessorCount());
                     int[] newKeys = new int[validKeys];
                     int[] newKeySuccessors = new int[validKeys + 1];
                     double[] newKeyProbabilities = new double[validKeys + 1];
@@ -172,14 +172,14 @@
                     }
 
                     for (int i = 0; i < blockSuccessorCount(); i++) {
-                        AbstractBeginNode successor = blockSuccessor(i);
+                        BeginNode successor = blockSuccessor(i);
                         if (!newSuccessors.contains(successor)) {
                             tool.deleteBranch(successor);
                         }
                         setBlockSuccessor(i, null);
                     }
 
-                    AbstractBeginNode[] successorsArray = newSuccessors.toArray(new AbstractBeginNode[newSuccessors.size()]);
+                    BeginNode[] successorsArray = newSuccessors.toArray(new BeginNode[newSuccessors.size()]);
                     IntegerSwitchNode newSwitch = graph().add(new IntegerSwitchNode(value(), successorsArray, newKeys, newKeyProbabilities, newKeySuccessors));
                     ((FixedWithNextNode) predecessor()).setNext(newSwitch);
                     GraphUtil.killWithUnusedFloatingInputs(this);
diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/JavaReadNode.java
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/JavaReadNode.java	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/JavaReadNode.java	Mon Apr 28 11:18:15 2014 +0200
@@ -22,9 +22,9 @@
  */
 package com.oracle.graal.nodes.extended;
 
+import com.oracle.graal.compiler.common.type.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.spi.*;
-import com.oracle.graal.nodes.type.*;
 
 /**
  * Read a raw memory location according to Java field or array read semantics. It will perform read
diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/LoadHubNode.java
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/LoadHubNode.java	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/LoadHubNode.java	Mon Apr 28 11:18:15 2014 +0200
@@ -24,11 +24,11 @@
 
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.api.meta.ResolvedJavaType.Representation;
+import com.oracle.graal.compiler.common.type.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.graph.spi.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.spi.*;
-import com.oracle.graal.nodes.type.*;
 
 /**
  * Loads an object's {@linkplain Representation#ObjectHub hub}. The object is not null-checked by
diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/LoadMethodNode.java
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/LoadMethodNode.java	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/LoadMethodNode.java	Mon Apr 28 11:18:15 2014 +0200
@@ -22,12 +22,10 @@
  */
 package com.oracle.graal.nodes.extended;
 
-import java.lang.reflect.*;
-
 import com.oracle.graal.api.meta.*;
+import com.oracle.graal.compiler.common.type.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.spi.*;
-import com.oracle.graal.nodes.type.*;
 
 /**
  * Loads a method from the virtual method table of a given hub.
@@ -45,8 +43,8 @@
         super(kind == Kind.Object ? StampFactory.objectNonNull() : StampFactory.forKind(kind));
         this.hub = hub;
         this.method = method;
-        assert !Modifier.isAbstract(method.getModifiers()) : "Cannot load abstract method from a hub";
-        assert !Modifier.isStatic(method.getModifiers()) : "Cannot load a static method from a hub";
+        assert !method.isAbstract() : "Cannot load abstract method from a hub";
+        assert !method.isStatic() : "Cannot load a static method from a hub";
         assert method.isInVirtualMethodTable();
     }
 
diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/LocationNode.java
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/LocationNode.java	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/LocationNode.java	Mon Apr 28 11:18:15 2014 +0200
@@ -23,11 +23,12 @@
 package com.oracle.graal.nodes.extended;
 
 import com.oracle.graal.api.meta.*;
+import com.oracle.graal.compiler.common.type.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.graph.Node.ValueNumberable;
+import com.oracle.graal.lir.gen.*;
 import com.oracle.graal.nodes.calc.*;
 import com.oracle.graal.nodes.spi.*;
-import com.oracle.graal.nodes.type.*;
 
 /**
  * A location for a memory access in terms of the kind of value accessed and how to access it. All
@@ -62,5 +63,5 @@
         // nothing to do...
     }
 
-    public abstract Value generateAddress(NodeLIRBuilderTool gen, Value base);
+    public abstract Value generateAddress(NodeMappableLIRBuilder builder, LIRGeneratorTool gen, Value base);
 }
diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/MembarNode.java
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/MembarNode.java	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/MembarNode.java	Mon Apr 28 11:18:15 2014 +0200
@@ -22,7 +22,7 @@
  */
 package com.oracle.graal.nodes.extended;
 
-import static com.oracle.graal.graph.UnsafeAccess.*;
+import static com.oracle.graal.compiler.common.UnsafeAccess.*;
 
 import java.lang.reflect.*;
 
@@ -30,10 +30,11 @@
 
 import com.oracle.graal.api.code.*;
 import com.oracle.graal.api.meta.*;
+import com.oracle.graal.compiler.common.*;
+import com.oracle.graal.compiler.common.type.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.spi.*;
-import com.oracle.graal.nodes.type.*;
 
 /**
  * Creates a memory barrier.
diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/MemoryCheckpoint.java
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/MemoryCheckpoint.java	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/MemoryCheckpoint.java	Mon Apr 28 11:18:15 2014 +0200
@@ -31,7 +31,7 @@
  * represented by location identities (i.e. change a value at one or more locations that belong to
  * these location identities).
  */
-public interface MemoryCheckpoint extends MemoryNode {
+public interface MemoryCheckpoint extends MemoryNode, NodeInterface {
 
     FixedNode asNode();
 
@@ -40,7 +40,7 @@
         /**
          * This method is used to determine which memory location is killed by this node. Returning
          * the special value {@link LocationIdentity#ANY_LOCATION} will kill all memory locations.
-         * 
+         *
          * @return the identity of the location killed by this node.
          */
         LocationIdentity getLocationIdentity();
@@ -53,7 +53,7 @@
          * This method is used to determine which set of memory locations is killed by this node.
          * Returning the special value {@link LocationIdentity#ANY_LOCATION} will kill all memory
          * locations.
-         * 
+         *
          * @return the identities of all locations killed by this node.
          */
         LocationIdentity[] getLocationIdentities();
diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/MemoryNode.java
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/MemoryNode.java	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/MemoryNode.java	Mon Apr 28 11:18:15 2014 +0200
@@ -22,12 +22,13 @@
  */
 package com.oracle.graal.nodes.extended;
 
+import com.oracle.graal.graph.*;
 import com.oracle.graal.nodes.*;
 
 /**
  * This interface marks nodes that are part of the memory graph.
  */
-public interface MemoryNode {
+public interface MemoryNode extends NodeInterface {
 
     ValueNode asNode();
 
diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/NullCheckNode.java
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/NullCheckNode.java	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/NullCheckNode.java	Mon Apr 28 11:18:15 2014 +0200
@@ -22,9 +22,9 @@
  */
 package com.oracle.graal.nodes.extended;
 
+import com.oracle.graal.compiler.common.type.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.spi.*;
-import com.oracle.graal.nodes.type.*;
 
 public class NullCheckNode extends DeoptimizingFixedWithNextNode implements LIRLowerable {
 
diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/OSRLocalNode.java
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/OSRLocalNode.java	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/OSRLocalNode.java	Mon Apr 28 11:18:15 2014 +0200
@@ -22,9 +22,9 @@
  */
 package com.oracle.graal.nodes.extended;
 
+import com.oracle.graal.compiler.common.type.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.nodes.*;
-import com.oracle.graal.nodes.type.*;
 
 @NodeInfo(nameTemplate = "OSRLocal({p#index})")
 public class OSRLocalNode extends AbstractLocalNode implements IterableNodeType {
diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/ReadNode.java
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/ReadNode.java	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/ReadNode.java	Mon Apr 28 11:18:15 2014 +0200
@@ -23,6 +23,7 @@
 package com.oracle.graal.nodes.extended;
 
 import com.oracle.graal.api.meta.*;
+import com.oracle.graal.compiler.common.type.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.graph.spi.*;
 import com.oracle.graal.nodes.*;
@@ -54,15 +55,18 @@
 
     @Override
     public void generate(NodeLIRBuilderTool gen) {
-        Value address = location().generateAddress(gen, gen.operand(object()));
+        Value address = location().generateAddress(gen, gen.getLIRGeneratorTool(), gen.operand(object()));
         PlatformKind readKind = gen.getLIRGeneratorTool().getPlatformKind(stamp());
-        gen.setResult(this, gen.getLIRGeneratorTool().emitLoad(readKind, address, this));
+        gen.setResult(this, gen.getLIRGeneratorTool().emitLoad(readKind, address, gen.state(this)));
     }
 
     @Override
     public Node canonical(CanonicalizerTool tool) {
         if (object() instanceof PiNode && ((PiNode) object()).getGuard() == getGuard()) {
-            return graph().add(new ReadNode(((PiNode) object()).getOriginalNode(), location(), stamp(), getGuard(), getBarrierType(), isCompressible()));
+            ReadNode readNode = graph().add(new ReadNode(((PiNode) object()).getOriginalNode(), location(), stamp(), getGuard(), getBarrierType(), isCompressible()));
+            readNode.setNullCheck(getNullCheck());
+            readNode.setStateBefore(stateBefore());
+            return readNode;
         }
         return canonicalizeRead(this, location(), object(), tool, isCompressible());
     }
@@ -140,7 +144,7 @@
         }
 
         ObjectStamp valueStamp = (ObjectStamp) parent.object().stamp();
-        ResolvedJavaType valueType = ObjectStamp.typeOrNull(valueStamp);
+        ResolvedJavaType valueType = StampTool.typeOrNull(valueStamp);
         if (valueType != null && field.getDeclaringClass().isAssignableFrom(valueType)) {
             if (piStamp.nonNull() == valueStamp.nonNull() && piStamp.alwaysNull() == valueStamp.alwaysNull()) {
                 replaceFirstInput(parent, parent.object());
diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/StoreHubNode.java
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/StoreHubNode.java	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/StoreHubNode.java	Mon Apr 28 11:18:15 2014 +0200
@@ -22,9 +22,9 @@
  */
 package com.oracle.graal.nodes.extended;
 
+import com.oracle.graal.compiler.common.type.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.spi.*;
-import com.oracle.graal.nodes.type.*;
 
 public final class StoreHubNode extends FixedWithNextNode implements Lowerable {
 
diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/SwitchNode.java
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/SwitchNode.java	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/SwitchNode.java	Mon Apr 28 11:18:15 2014 +0200
@@ -25,16 +25,17 @@
 import java.util.*;
 
 import com.oracle.graal.api.meta.*;
+import com.oracle.graal.compiler.common.*;
+import com.oracle.graal.compiler.common.type.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.nodes.*;
-import com.oracle.graal.nodes.type.*;
 
 /**
  * The {@code SwitchNode} class is the base of both lookup and table switches.
  */
 public abstract class SwitchNode extends ControlSplitNode {
 
-    @Successor private final NodeSuccessorList successors;
+    @Successor private final NodeSuccessorList successors;
     @Input private ValueNode value;
     private double[] keyProbabilities;
     private int[] keySuccessors;
@@ -45,7 +46,7 @@
      * @param value the instruction that provides the value to be switched over
      * @param successors the list of successors of this switch
      */
-    public SwitchNode(ValueNode value, AbstractBeginNode[] successors, int[] keySuccessors, double[] keyProbabilities) {
+    public SwitchNode(ValueNode value, BeginNode[] successors, int[] keySuccessors, double[] keyProbabilities) {
         super(StampFactory.forVoid());
         assert value.getKind() == Kind.Int || value.getKind() == Kind.Long || value.getKind() == Kind.Object : value.getKind() + " key not supported by SwitchNode";
         assert keySuccessors.length == keyProbabilities.length;
@@ -76,7 +77,7 @@
     }
 
     @Override
-    public double probability(AbstractBeginNode successor) {
+    public double probability(BeginNode successor) {
         double sum = 0;
         for (int i = 0; i < keySuccessors.length; i++) {
             if (successors.get(keySuccessors[i]) == successor) {
@@ -87,7 +88,7 @@
     }
 
     @Override
-    public void setProbability(AbstractBeginNode successor, double value) {
+    public void setProbability(BeginNode successor, double value) {
         double changeInProbability = 0;
         int nonZeroProbabilityCases = 0;
         for (int i = 0; i < keySuccessors.length; i++) {
@@ -139,7 +140,7 @@
     /**
      * Returns the successor for the key at the given index.
      */
-    public AbstractBeginNode keySuccessor(int i) {
+    public BeginNode keySuccessor(int i) {
         return successors.get(keySuccessors[i]);
     }
 
@@ -157,11 +158,11 @@
         return keySuccessors[keySuccessors.length - 1];
     }
 
-    public AbstractBeginNode blockSuccessor(int i) {
+    public BeginNode blockSuccessor(int i) {
         return successors.get(i);
     }
 
-    public void setBlockSuccessor(int i, AbstractBeginNode s) {
+    public void setBlockSuccessor(int i, BeginNode s) {
         successors.set(i, s);
     }
 
@@ -174,7 +175,7 @@
      * 
      * @return the default successor
      */
-    public AbstractBeginNode defaultSuccessor() {
+    public BeginNode defaultSuccessor() {
         if (defaultSuccessorIndex() == -1) {
             throw new GraalInternalError("unexpected");
         }
diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/UnboxNode.java
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/UnboxNode.java	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/UnboxNode.java	Mon Apr 28 11:18:15 2014 +0200
@@ -23,12 +23,12 @@
 package com.oracle.graal.nodes.extended;
 
 import com.oracle.graal.api.meta.*;
+import com.oracle.graal.compiler.common.type.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.graph.spi.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.calc.*;
 import com.oracle.graal.nodes.spi.*;
-import com.oracle.graal.nodes.type.*;
 
 public class UnboxNode extends FloatingNode implements Virtualizable, Lowerable, Canonicalizable {
 
diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/UnsafeAccessNode.java
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/UnsafeAccessNode.java	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/UnsafeAccessNode.java	Mon Apr 28 11:18:15 2014 +0200
@@ -23,6 +23,7 @@
 package com.oracle.graal.nodes.extended;
 
 import com.oracle.graal.api.meta.*;
+import com.oracle.graal.compiler.common.type.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.graph.spi.*;
 import com.oracle.graal.nodes.*;
@@ -66,7 +67,7 @@
             long constantOffset = offset().asConstant().asLong();
 
             // Try to canonicalize to a field access.
-            ResolvedJavaType receiverType = ObjectStamp.typeOrNull(object());
+            ResolvedJavaType receiverType = StampTool.typeOrNull(object());
             if (receiverType != null) {
                 ResolvedJavaField field = receiverType.findInstanceFieldWithOffset(constantOffset);
                 // No need for checking that the receiver is non-null. The field access includes
@@ -78,15 +79,15 @@
                 }
             }
         }
-        // Temporarily disable this as it appears to break truffle.
-        // ResolvedJavaType receiverType = ObjectStamp.typeOrNull(object());
-        // if (receiverType != null && receiverType.isArray()) {
-        // LocationIdentity identity =
-        // NamedLocationIdentity.getArrayLocation(receiverType.getComponentType().getKind());
-        // // Try to build a better location node
-        // ValueNode location = offset();
-        // return cloneAsArrayAccess(location, identity);
-        // }
+        if (this.getLocationIdentity() == LocationIdentity.ANY_LOCATION) {
+            ResolvedJavaType receiverType = StampTool.typeOrNull(object());
+            // Try to build a better location identity.
+            if (receiverType != null && receiverType.isArray()) {
+                LocationIdentity identity = NamedLocationIdentity.getArrayLocation(receiverType.getComponentType().getKind());
+                assert !graph().isAfterFloatingReadPhase() : "cannot add more precise memory location after floating read phase";
+                return cloneAsArrayAccess(offset(), identity);
+            }
+        }
 
         return this;
     }
diff -r 3dde8d8c95b8 -r 40d0022115ee 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	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/UnsafeCastNode.java	Mon Apr 28 11:18:15 2014 +0200
@@ -23,6 +23,7 @@
 package com.oracle.graal.nodes.extended;
 
 import com.oracle.graal.api.meta.*;
+import com.oracle.graal.compiler.common.type.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.graph.spi.*;
 import com.oracle.graal.nodes.*;
@@ -50,7 +51,7 @@
     }
 
     public UnsafeCastNode(ValueNode object, ResolvedJavaType toType, boolean exactType, boolean nonNull) {
-        this(object, toType.getKind() == Kind.Object ? StampFactory.object(toType, exactType, nonNull || ObjectStamp.isObjectNonNull(object.stamp())) : StampFactory.forKind(toType.getKind()));
+        this(object, toType.getKind() == Kind.Object ? StampFactory.object(toType, exactType, nonNull || StampTool.isObjectNonNull(object.stamp())) : StampFactory.forKind(toType.getKind()));
     }
 
     @Override
@@ -59,36 +60,27 @@
     }
 
     @Override
+    public boolean inferStamp() {
+        if (stamp() instanceof ObjectStamp && object.stamp() instanceof ObjectStamp) {
+            return updateStamp(((ObjectStamp) object.stamp()).castTo((ObjectStamp) stamp()));
+        }
+        return updateStamp(object.stamp().join(stamp()));
+    }
+
+    @Override
     public Node canonical(CanonicalizerTool tool) {
         assert getKind() == Kind.Object && object.getKind() == Kind.Object;
-
-        ObjectStamp my = (ObjectStamp) stamp();
-        ObjectStamp other = (ObjectStamp) object.stamp();
-
-        if (my.type() == null || other.type() == null) {
-            return this;
-        }
-        if (my.isExactType() && !other.isExactType()) {
+        if (stamp().equals(object.stamp())) {
+            return object;
+        } else {
             return this;
         }
-        if (my.nonNull() && !other.nonNull()) {
-            return this;
-        }
-        if (!my.type().isAssignableFrom(other.type())) {
-            return this;
-        }
-        /*
-         * The unsafe cast does not add any new type information, so it can be removed. Note that
-         * this means that the unsafe cast cannot be used to "drop" type information (in which case
-         * it must not be canonicalized in any case).
-         */
-        return object;
     }
 
     @Override
     public void virtualize(VirtualizerTool tool) {
         State state = tool.getObjectState(object);
-        if (state != null && state.getState() == EscapeState.Virtual && ObjectStamp.typeOrNull(this) != null && ObjectStamp.typeOrNull(this).isAssignableFrom(state.getVirtualObject().type())) {
+        if (state != null && state.getState() == EscapeState.Virtual && StampTool.typeOrNull(this) != null && StampTool.typeOrNull(this).isAssignableFrom(state.getVirtualObject().type())) {
             tool.replaceWithVirtual(state.getVirtualObject());
         }
     }
diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/UnsafeLoadNode.java
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/UnsafeLoadNode.java	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/UnsafeLoadNode.java	Mon Apr 28 11:18:15 2014 +0200
@@ -22,14 +22,14 @@
  */
 package com.oracle.graal.nodes.extended;
 
-import static com.oracle.graal.graph.UnsafeAccess.*;
+import static com.oracle.graal.compiler.common.UnsafeAccess.*;
 
 import com.oracle.graal.api.meta.*;
+import com.oracle.graal.compiler.common.type.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.java.*;
 import com.oracle.graal.nodes.spi.*;
-import com.oracle.graal.nodes.type.*;
 
 /**
  * Load of a value from a location specified as an offset relative to an object. No null check is
diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/UnsafeStoreNode.java
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/UnsafeStoreNode.java	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/UnsafeStoreNode.java	Mon Apr 28 11:18:15 2014 +0200
@@ -22,14 +22,14 @@
  */
 package com.oracle.graal.nodes.extended;
 
-import static com.oracle.graal.graph.UnsafeAccess.*;
+import static com.oracle.graal.compiler.common.UnsafeAccess.*;
 
 import com.oracle.graal.api.meta.*;
+import com.oracle.graal.compiler.common.type.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.java.*;
 import com.oracle.graal.nodes.spi.*;
-import com.oracle.graal.nodes.type.*;
 
 /**
  * Store of a value at a location specified as an offset relative to an object. No null check is
diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/ValueAnchorNode.java
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/ValueAnchorNode.java	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/ValueAnchorNode.java	Mon Apr 28 11:18:15 2014 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2011, 2014, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -22,19 +22,19 @@
  */
 package com.oracle.graal.nodes.extended;
 
+import com.oracle.graal.compiler.common.type.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.graph.spi.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.calc.*;
 import com.oracle.graal.nodes.spi.*;
-import com.oracle.graal.nodes.type.*;
 import com.oracle.graal.nodes.util.*;
 
 /**
  * The ValueAnchor instruction keeps non-CFG (floating) nodes above a certain point in the graph.
  */
 @NodeInfo(allowedUsageTypes = {InputType.Anchor, InputType.Guard})
-public final class ValueAnchorNode extends FixedWithNextNode implements LIRLowerable, Simplifiable, Virtualizable, GuardingNode {
+public final class ValueAnchorNode extends FixedWithNextNode implements LIRLowerable, Simplifiable, Virtualizable, AnchoringNode, GuardingNode {
 
     @Input(InputType.Guard) private ValueNode anchored;
 
@@ -91,7 +91,7 @@
 
     @Override
     public void virtualize(VirtualizerTool tool) {
-        if (anchored != null && !(anchored instanceof AbstractBeginNode)) {
+        if (anchored != null && !(anchored instanceof BeginNode)) {
             State state = tool.getObjectState(anchored);
             if (state == null || state.getState() != EscapeState.Virtual) {
                 return;
diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/WriteNode.java
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/WriteNode.java	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/WriteNode.java	Mon Apr 28 11:18:15 2014 +0200
@@ -44,7 +44,7 @@
 
     @Override
     public void generate(NodeLIRBuilderTool gen) {
-        Value address = location().generateAddress(gen, gen.operand(object()));
+        Value address = location().generateAddress(gen, gen.getLIRGeneratorTool(), gen.operand(object()));
         // It's possible a constant was forced for other usages so inspect the value directly and
         // use a constant if it can be directly stored.
         Value v;
@@ -54,7 +54,7 @@
             v = gen.operand(value());
         }
         PlatformKind writeKind = gen.getLIRGeneratorTool().getPlatformKind(value().stamp());
-        gen.getLIRGeneratorTool().emitStore(writeKind, address, v, this);
+        gen.getLIRGeneratorTool().emitStore(writeKind, address, v, gen.state(this));
     }
 
     @Override
diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/AbstractNewArrayNode.java
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/AbstractNewArrayNode.java	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/AbstractNewArrayNode.java	Mon Apr 28 11:18:15 2014 +0200
@@ -22,10 +22,10 @@
  */
 package com.oracle.graal.nodes.java;
 
+import com.oracle.graal.compiler.common.type.*;
 import com.oracle.graal.graph.spi.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.spi.*;
-import com.oracle.graal.nodes.type.*;
 
 /**
  * The {@code AbstractNewArrayNode} is used for all 1-dimensional array allocations.
diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/AbstractNewObjectNode.java
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/AbstractNewObjectNode.java	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/AbstractNewObjectNode.java	Mon Apr 28 11:18:15 2014 +0200
@@ -24,12 +24,12 @@
 
 import java.util.*;
 
+import com.oracle.graal.compiler.common.type.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.graph.spi.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.extended.*;
 import com.oracle.graal.nodes.spi.*;
-import com.oracle.graal.nodes.type.*;
 
 /**
  * The {@code AbstractNewObjectNode} is the base class for the new instance and new array nodes.
diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/AccessArrayNode.java
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/AccessArrayNode.java	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/AccessArrayNode.java	Mon Apr 28 11:18:15 2014 +0200
@@ -22,8 +22,8 @@
  */
 package com.oracle.graal.nodes.java;
 
+import com.oracle.graal.compiler.common.type.*;
 import com.oracle.graal.nodes.*;
-import com.oracle.graal.nodes.type.*;
 
 /**
  * This the base class of all array operations.
diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/AccessFieldNode.java
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/AccessFieldNode.java	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/AccessFieldNode.java	Mon Apr 28 11:18:15 2014 +0200
@@ -22,12 +22,10 @@
  */
 package com.oracle.graal.nodes.java;
 
-import java.lang.reflect.*;
-
 import com.oracle.graal.api.meta.*;
+import com.oracle.graal.compiler.common.type.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.spi.*;
-import com.oracle.graal.nodes.type.*;
 
 /**
  * The base class of all instructions that access fields.
@@ -70,7 +68,7 @@
      * @return {@code true} if this field access is to a static field
      */
     public boolean isStatic() {
-        return Modifier.isStatic(field.getModifiers());
+        return field.isStatic();
     }
 
     /**
@@ -79,7 +77,7 @@
      * @return {@code true} if the field is resolved and declared volatile
      */
     public boolean isVolatile() {
-        return Modifier.isVolatile(field.getModifiers());
+        return field.isVolatile();
     }
 
     @Override
diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/AccessIndexedNode.java
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/AccessIndexedNode.java	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/AccessIndexedNode.java	Mon Apr 28 11:18:15 2014 +0200
@@ -23,9 +23,9 @@
 package com.oracle.graal.nodes.java;
 
 import com.oracle.graal.api.meta.*;
+import com.oracle.graal.compiler.common.type.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.spi.*;
-import com.oracle.graal.nodes.type.*;
 
 /**
  * The {@code AccessIndexedNode} class is the base class of instructions that read or write elements
diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/AccessMonitorNode.java
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/AccessMonitorNode.java	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/AccessMonitorNode.java	Mon Apr 28 11:18:15 2014 +0200
@@ -23,10 +23,10 @@
 package com.oracle.graal.nodes.java;
 
 import com.oracle.graal.api.code.*;
+import com.oracle.graal.compiler.common.type.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.extended.*;
-import com.oracle.graal.nodes.type.*;
 
 /**
  * The {@code AccessMonitorNode} is the base class of both monitor acquisition and release.
diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/ArrayLengthNode.java
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/ArrayLengthNode.java	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/ArrayLengthNode.java	Mon Apr 28 11:18:15 2014 +0200
@@ -23,11 +23,12 @@
 package com.oracle.graal.nodes.java;
 
 import com.oracle.graal.api.meta.*;
+import com.oracle.graal.compiler.common.type.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.graph.spi.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.spi.*;
-import com.oracle.graal.nodes.type.*;
+import com.oracle.graal.nodes.util.*;
 
 /**
  * The {@code ArrayLength} instruction gets the length of an array.
@@ -57,18 +58,30 @@
     /**
      * Gets the length of an array if possible.
      *
-     * @param graph TODO
-     * @param array an array
-     *
      * @return a node representing the length of {@code array} or null if it is not available
      */
-    public static ValueNode readArrayLength(StructuredGraph graph, ValueNode array, ConstantReflectionProvider constantReflection) {
-        if (array instanceof ArrayLengthProvider) {
-            ValueNode length = ((ArrayLengthProvider) array).length();
+    public static ValueNode readArrayLength(StructuredGraph graph, ValueNode originalArray, ConstantReflectionProvider constantReflection) {
+        ArrayLengthProvider foundArrayLengthProvider = null;
+        ValueNode result = originalArray;
+        while (true) {
+            if (result instanceof ArrayLengthProvider) {
+                foundArrayLengthProvider = (ArrayLengthProvider) result;
+                break;
+            }
+            if (result instanceof ValueProxy) {
+                result = ((ValueProxy) result).getOriginalNode();
+            } else {
+                break;
+            }
+        }
+
+        if (foundArrayLengthProvider != null) {
+            ValueNode length = foundArrayLengthProvider.length();
             if (length != null) {
                 return length;
             }
         }
+        ValueNode array = GraphUtil.unproxify(originalArray);
         if (constantReflection != null && array.isConstant() && !array.isNullConstant()) {
             Constant constantValue = array.asConstant();
             if (constantValue != null && constantValue.isNonNull()) {
diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/AtomicReadAndAddNode.java
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/AtomicReadAndAddNode.java	Mon Apr 28 11:18:15 2014 +0200
@@ -0,0 +1,88 @@
+/*
+ * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.graal.nodes.java;
+
+import static com.oracle.graal.compiler.common.UnsafeAccess.*;
+
+import com.oracle.graal.api.meta.*;
+import com.oracle.graal.compiler.common.type.*;
+import com.oracle.graal.graph.*;
+import com.oracle.graal.nodes.*;
+import com.oracle.graal.nodes.extended.*;
+import com.oracle.graal.nodes.spi.*;
+
+import sun.misc.*;
+
+/**
+ * Represents an atomic read-and-add operation like {@link Unsafe#getAndAddInt(Object, long, int)}.
+ */
+@NodeInfo(allowedUsageTypes = {InputType.Memory})
+public class AtomicReadAndAddNode extends AbstractMemoryCheckpoint implements LIRLowerable, MemoryCheckpoint.Single {
+
+    @Input private ValueNode object;
+    @Input private ValueNode offset;
+    @Input private ValueNode delta;
+
+    private final LocationIdentity locationIdentity;
+
+    public AtomicReadAndAddNode(ValueNode object, ValueNode offset, ValueNode delta, LocationIdentity locationIdentity) {
+        super(StampFactory.forKind(delta.getKind()));
+        this.object = object;
+        this.offset = offset;
+        this.delta = delta;
+        this.locationIdentity = locationIdentity;
+    }
+
+    public ValueNode object() {
+        return object;
+    }
+
+    public ValueNode offset() {
+        return offset;
+    }
+
+    public ValueNode delta() {
+        return delta;
+    }
+
+    public LocationIdentity getLocationIdentity() {
+        return locationIdentity;
+    }
+
+    public void generate(NodeLIRBuilderTool gen) {
+        LocationNode location = IndexedLocationNode.create(getLocationIdentity(), delta.getKind(), 0, offset, graph(), 1);
+        Value address = location.generateAddress(gen, gen.getLIRGeneratorTool(), gen.operand(object()));
+        Value result = gen.getLIRGeneratorTool().emitAtomicReadAndAdd(address, gen.operand(delta));
+        gen.setResult(this, result);
+    }
+
+    @NodeIntrinsic
+    public static int getAndAddInt(Object object, long offset, int delta, @ConstantNodeParameter @SuppressWarnings("unused") LocationIdentity locationIdentity) {
+        return unsafe.getAndAddInt(object, offset, delta);
+    }
+
+    @NodeIntrinsic
+    public static long getAndAddLong(Object object, long offset, long delta, @ConstantNodeParameter @SuppressWarnings("unused") LocationIdentity locationIdentity) {
+        return unsafe.getAndAddLong(object, offset, delta);
+    }
+}
diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/AtomicReadAndWriteNode.java
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/AtomicReadAndWriteNode.java	Mon Apr 28 11:18:15 2014 +0200
@@ -0,0 +1,99 @@
+/*
+ * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.graal.nodes.java;
+
+import static com.oracle.graal.compiler.common.UnsafeAccess.*;
+
+import com.oracle.graal.api.meta.*;
+import com.oracle.graal.compiler.common.type.*;
+import com.oracle.graal.nodes.*;
+import com.oracle.graal.nodes.extended.*;
+import com.oracle.graal.nodes.spi.*;
+
+import sun.misc.*;
+
+/**
+ * Represents an atomic read-and-write operation like {@link Unsafe#getAndSetInt(Object, long, int)}
+ * .
+ */
+public class AtomicReadAndWriteNode extends AbstractMemoryCheckpoint implements Lowerable, MemoryCheckpoint.Single {
+
+    @Input private ValueNode object;
+    @Input private ValueNode offset;
+    @Input private ValueNode newValue;
+
+    private final Kind valueKind;
+    private final LocationIdentity locationIdentity;
+
+    public AtomicReadAndWriteNode(ValueNode object, ValueNode offset, ValueNode newValue, Kind valueKind, LocationIdentity locationIdentity) {
+        super(StampFactory.forKind(newValue.getKind()));
+        this.object = object;
+        this.offset = offset;
+        this.newValue = newValue;
+        this.valueKind = valueKind;
+        this.locationIdentity = locationIdentity;
+    }
+
+    public ValueNode object() {
+        return object;
+    }
+
+    public ValueNode offset() {
+        return offset;
+    }
+
+    public ValueNode newValue() {
+        return newValue;
+    }
+
+    public Kind getValueKind() {
+        return valueKind;
+    }
+
+    public LocationIdentity getLocationIdentity() {
+        return locationIdentity;
+    }
+
+    public void lower(LoweringTool tool) {
+        tool.getLowerer().lower(this, tool);
+    }
+
+    @NodeIntrinsic
+    public static int getAndSetInt(Object object, long offset, int newValue, @SuppressWarnings("unused") @ConstantNodeParameter Kind valueKind,
+                    @ConstantNodeParameter @SuppressWarnings("unused") LocationIdentity locationIdentity) {
+        return unsafe.getAndSetInt(object, offset, newValue);
+    }
+
+    @NodeIntrinsic
+    public static long getAndSetLong(Object object, long offset, long newValue, @SuppressWarnings("unused") @ConstantNodeParameter Kind valueKind,
+                    @ConstantNodeParameter @SuppressWarnings("unused") LocationIdentity locationIdentity) {
+        return unsafe.getAndSetLong(object, offset, newValue);
+    }
+
+    @NodeIntrinsic
+    public static Object getAndSetObject(Object object, long offset, Object newValue, @SuppressWarnings("unused") @ConstantNodeParameter Kind valueKind,
+                    @ConstantNodeParameter @SuppressWarnings("unused") LocationIdentity locationIdentity) {
+        return unsafe.getAndSetObject(object, offset, newValue);
+    }
+
+}
diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/CheckCastDynamicNode.java
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/CheckCastDynamicNode.java	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/CheckCastDynamicNode.java	Mon Apr 28 11:18:15 2014 +0200
@@ -73,7 +73,7 @@
     public Node canonical(CanonicalizerTool tool) {
         assert object() != null : this;
 
-        if (ObjectStamp.isObjectAlwaysNull(object())) {
+        if (StampTool.isObjectAlwaysNull(object())) {
             return object();
         }
         if (hub.isConstant()) {
diff -r 3dde8d8c95b8 -r 40d0022115ee 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	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/CheckCastNode.java	Mon Apr 28 11:18:15 2014 +0200
@@ -28,6 +28,7 @@
 
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.api.meta.ProfilingInfo.TriState;
+import com.oracle.graal.compiler.common.type.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.graph.spi.*;
 import com.oracle.graal.nodes.*;
@@ -106,7 +107,7 @@
             // This is a check cast that will always fail
             condition = LogicConstantNode.contradiction(graph());
             stamp = StampFactory.declared(type);
-        } else if (ObjectStamp.isObjectNonNull(object)) {
+        } else if (StampTool.isObjectNonNull(object)) {
             condition = graph().addWithoutUnique(new InstanceOfNode(type, object, profile));
         } else {
             if (profile != null && profile.getNullSeen() == TriState.FALSE) {
@@ -141,7 +142,7 @@
     public Node canonical(CanonicalizerTool tool) {
         assert object() != null : this;
 
-        ResolvedJavaType objectType = ObjectStamp.typeOrNull(object());
+        ResolvedJavaType objectType = StampTool.typeOrNull(object());
         if (objectType != null && type.isAssignableFrom(objectType)) {
             // we don't have to check for null types here because they will also pass the
             // checkcast.
@@ -160,7 +161,7 @@
             }
         }
 
-        if (ObjectStamp.isObjectAlwaysNull(object())) {
+        if (StampTool.isObjectAlwaysNull(object())) {
             return object();
         }
         if (tool.assumptions() != null && tool.assumptions().useOptimisticAssumptions()) {
diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/CompareAndSwapNode.java
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/CompareAndSwapNode.java	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/CompareAndSwapNode.java	Mon Apr 28 11:18:15 2014 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2011, 2014, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -22,14 +22,14 @@
  */
 package com.oracle.graal.nodes.java;
 
-import static com.oracle.graal.graph.UnsafeAccess.*;
+import static com.oracle.graal.compiler.common.UnsafeAccess.*;
 
 import com.oracle.graal.api.meta.*;
+import com.oracle.graal.compiler.common.type.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.extended.*;
 import com.oracle.graal.nodes.spi.*;
-import com.oracle.graal.nodes.type.*;
 
 /**
  * Represents an atomic compare-and-swap operation The result is a boolean that contains whether the
@@ -45,6 +45,19 @@
 
     private final Kind valueKind;
     private final int displacement;
+    private final LocationIdentity locationIdentity;
+
+    public CompareAndSwapNode(ValueNode object, int displacement, ValueNode offset, ValueNode expected, ValueNode newValue, Kind valueKind, LocationIdentity locationIdentity) {
+        super(StampFactory.forKind(Kind.Boolean.getStackKind()));
+        assert expected.stamp().isCompatible(newValue.stamp());
+        this.object = object;
+        this.offset = offset;
+        this.expected = expected;
+        this.newValue = newValue;
+        this.displacement = displacement;
+        this.valueKind = valueKind;
+        this.locationIdentity = locationIdentity;
+    }
 
     public ValueNode object() {
         return object;
@@ -70,20 +83,9 @@
         return valueKind;
     }
 
-    public CompareAndSwapNode(ValueNode object, int displacement, ValueNode offset, ValueNode expected, ValueNode newValue, Kind valueKind) {
-        super(StampFactory.forKind(Kind.Boolean.getStackKind()));
-        assert expected.stamp().isCompatible(newValue.stamp());
-        this.object = object;
-        this.offset = offset;
-        this.expected = expected;
-        this.newValue = newValue;
-        this.displacement = displacement;
-        this.valueKind = valueKind;
-    }
-
     @Override
     public LocationIdentity getLocationIdentity() {
-        return LocationIdentity.ANY_LOCATION;
+        return locationIdentity;
     }
 
     @Override
@@ -94,19 +96,19 @@
     // specialized on value type until boxing/unboxing is sorted out in intrinsification
     @NodeIntrinsic
     public static boolean compareAndSwap(Object object, @ConstantNodeParameter int displacement, long offset, Object expected, Object newValue,
-                    @SuppressWarnings("unused") @ConstantNodeParameter Kind valueKind) {
+                    @SuppressWarnings("unused") @ConstantNodeParameter Kind valueKind, @SuppressWarnings("unused") @ConstantNodeParameter LocationIdentity locationIdentity) {
         return unsafe.compareAndSwapObject(object, displacement + offset, expected, newValue);
     }
 
     @NodeIntrinsic
     public static boolean compareAndSwap(Object object, @ConstantNodeParameter int displacement, long offset, long expected, long newValue,
-                    @SuppressWarnings("unused") @ConstantNodeParameter Kind valueKind) {
+                    @SuppressWarnings("unused") @ConstantNodeParameter Kind valueKind, @SuppressWarnings("unused") @ConstantNodeParameter LocationIdentity locationIdentity) {
         return unsafe.compareAndSwapLong(object, displacement + offset, expected, newValue);
     }
 
     @NodeIntrinsic
     public static boolean compareAndSwap(Object object, @ConstantNodeParameter int displacement, long offset, int expected, int newValue,
-                    @SuppressWarnings("unused") @ConstantNodeParameter Kind valueKind) {
+                    @SuppressWarnings("unused") @ConstantNodeParameter Kind valueKind, @SuppressWarnings("unused") @ConstantNodeParameter LocationIdentity locationIdentity) {
         return unsafe.compareAndSwapInt(object, displacement + offset, expected, newValue);
     }
 }
diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/DynamicNewArrayNode.java
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/DynamicNewArrayNode.java	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/DynamicNewArrayNode.java	Mon Apr 28 11:18:15 2014 +0200
@@ -26,10 +26,10 @@
 import java.util.*;
 
 import com.oracle.graal.api.meta.*;
+import com.oracle.graal.compiler.common.type.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.graph.spi.*;
 import com.oracle.graal.nodes.*;
-import com.oracle.graal.nodes.type.*;
 
 /**
  * The {@code DynamicNewArrayNode} is used for allocation of arrays when the type is not a
diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/DynamicNewInstanceNode.java
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/DynamicNewInstanceNode.java	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/DynamicNewInstanceNode.java	Mon Apr 28 11:18:15 2014 +0200
@@ -23,10 +23,10 @@
 package com.oracle.graal.nodes.java;
 
 import com.oracle.graal.api.meta.*;
+import com.oracle.graal.compiler.common.type.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.graph.spi.*;
 import com.oracle.graal.nodes.*;
-import com.oracle.graal.nodes.type.*;
 
 public class DynamicNewInstanceNode extends AbstractNewObjectNode implements Canonicalizable {
 
diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/ExceptionObjectNode.java
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/ExceptionObjectNode.java	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/ExceptionObjectNode.java	Mon Apr 28 11:18:15 2014 +0200
@@ -22,21 +22,18 @@
  */
 package com.oracle.graal.nodes.java;
 
-import java.util.*;
-
-import com.oracle.graal.api.code.*;
 import com.oracle.graal.api.meta.*;
+import com.oracle.graal.compiler.common.type.*;
 import com.oracle.graal.graph.*;
-import com.oracle.graal.graph.spi.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.extended.*;
 import com.oracle.graal.nodes.spi.*;
-import com.oracle.graal.nodes.type.*;
 
 /**
  * The entry to an exception handler with the exception coming from a call (as opposed to a local
  * throw instruction or implicit exception).
  */
+@NodeInfo(allowedUsageTypes = {InputType.Memory})
 public class ExceptionObjectNode extends DispatchBeginNode implements Lowerable, MemoryCheckpoint.Single {
 
     public ExceptionObjectNode(MetaAccessProvider metaAccess) {
@@ -49,56 +46,13 @@
     }
 
     @Override
-    public void simplify(SimplifierTool tool) {
-        //
-    }
-
-    private boolean isLowered() {
-        return (stamp() == StampFactory.forVoid());
-    }
-
-    /**
-     * The frame state upon entry to an exception handler is such that it is a
-     * {@link BytecodeFrame#rethrowException rethrow exception} state and the stack contains exactly
-     * the exception object (per the JVM spec) to rethrow. This means that the code creating this
-     * state (i.e. the {@link LoadExceptionObjectNode}) cannot cause a deoptimization as the
-     * runtime/interpreter would not have a valid location for the exception object to be rethrown.
-     */
-    @Override
     public void lower(LoweringTool tool) {
-        if (isLowered()) {
-            return;
-        }
-        LoadExceptionObjectNode loadException = graph().add(new LoadExceptionObjectNode(stamp()));
-        loadException.setStateAfter(stateAfter());
-        List guardedNodes = new ArrayList<>();
-        for (Node usage : usages().snapshot()) {
-            if (usage instanceof GuardedNode) {
-                // can't replace the guard with LoadExceptionObjectNode as it is not a GuardingNode
-                // so temporarily change it to remove the GuardedNode from usages
-                GuardedNode guardedNode = (GuardedNode) usage;
-                guardedNode.setGuard(graph().add(new BeginNode()));
-                guardedNodes.add(guardedNode);
-            }
-        }
-        replaceAtUsages(loadException);
-        for (GuardedNode guardedNode : guardedNodes) {
-            BeginNode dummyGuard = (BeginNode) guardedNode.getGuard();
-            guardedNode.setGuard(this);
-            graph().removeFixed(dummyGuard);
-        }
-        graph().addAfterFixed(this, loadException);
-        setStateAfter(null);
-        setStamp(StampFactory.forVoid());
-        loadException.lower(tool);
+        tool.getLowerer().lower(this, tool);
     }
 
     @Override
     public boolean verify() {
-        if (isLowered()) {
-            return true;
-        }
-        assertTrue(stateAfter() != null || stamp() == StampFactory.forVoid(), "an exception handler needs a frame state");
+        assertTrue(stateAfter() != null, "an exception handler needs a frame state");
         return super.verify();
     }
 
diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/InstanceOfDynamicNode.java
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/InstanceOfDynamicNode.java	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/InstanceOfDynamicNode.java	Mon Apr 28 11:18:15 2014 +0200
@@ -47,8 +47,8 @@
         this.mirror = mirror;
         this.object = object;
         assert mirror.getKind() == Kind.Object : mirror.getKind();
-        assert ObjectStamp.isExactType(mirror);
-        assert ObjectStamp.typeOrNull(mirror).getName().equals("Ljava/lang/Class;");
+        assert StampTool.isExactType(mirror);
+        assert StampTool.typeOrNull(mirror).getName().equals("Ljava/lang/Class;");
     }
 
     @Override
diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/InstanceOfNode.java
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/InstanceOfNode.java	Fri Apr 25 16:21:07 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/InstanceOfNode.java	Mon Apr 28 11:18:15 2014 +0200
@@ -23,31 +23,31 @@
 package com.oracle.graal.nodes.java;
 
 import com.oracle.graal.api.meta.*;
+import com.oracle.graal.api.meta.ProfilingInfo.TriState;
+import com.oracle.graal.compiler.common.type.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.graph.spi.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.calc.*;
 import com.oracle.graal.nodes.spi.*;
-import com.oracle.graal.nodes.type.*;
 
 /**
  * The {@code InstanceOfNode} represents an instanceof test.
  */
-public final class InstanceOfNode extends LogicNode implements Canonicalizable, Lowerable, Virtualizable {
+public final class InstanceOfNode extends UnaryOpLogicNode implements Canonicalizable, Lowerable, Virtualizable {
 
-    @Input private ValueNode object;
     private final ResolvedJavaType type;
     private JavaTypeProfile profile;
 
     /**
      * Constructs a new InstanceOfNode.
-     * 
+     *
      * @param type the target type of the instanceof check
      * @param object the object being tested by the instanceof
      */
     public InstanceOfNode(ResolvedJavaType type, ValueNode object, JavaTypeProfile profile) {
+        super(object);
         this.type = type;
-        this.object = object;
         this.profile = profile;
         assert type != null;
     }
@@ -59,13 +59,39 @@
 
     @Override
     public Node canonical(CanonicalizerTool tool) {
-        Stamp stamp = object().stamp();
+        switch (evaluate(object())) {
+            case FALSE:
+                return LogicConstantNode.contradiction(graph());
+            case TRUE:
+                return LogicConstantNode.tautology(graph());
+            case UNKNOWN:
+                Stamp stamp = object().stamp();
+                if (stamp instanceof ObjectStamp) {
+                    ObjectStamp objectStamp = (ObjectStamp) stamp;
+                    ResolvedJavaType stampType = objectStamp.type();
+                    if (stampType != null && type().isAssignableFrom(stampType)) {
+                        if (!objectStamp.nonNull()) {
+                            // the instanceof matches if the object is non-null, so return true
+                            // depending on the null-ness.
+                            IsNullNode isNull = graph().unique(new IsNullNode(object()));
+                            return graph().unique(new LogicNegationNode(isNull));
+                        }
+                    }
+                }
+                return this;
+        }
+        return this;
+    }
+
+    @Override
+    public TriState evaluate(ValueNode forObject) {
+        Stamp stamp = forObject.stamp();
         if (!(stamp instanceof ObjectStamp)) {
-            return this;
+            return TriState.UNKNOWN;
         }
         ObjectStamp objectStamp = (ObjectStamp) stamp;
         if (objectStamp.alwaysNull()) {
-            return LogicConstantNode.contradiction(graph());
+            return TriState.FALSE;
         }
 
         ResolvedJavaType stampType = objectStamp.type();
@@ -74,34 +100,25 @@
             if (subType) {
                 if (objectStamp.nonNull()) {
                     // the instanceOf matches, so return true
-                    return LogicConstantNode.tautology(graph());
-                } else {
-                    // the instanceof matches if the object is non-null, so return true depending on
-                    // the null-ness.
-                    IsNullNode isNull = graph().unique(new IsNullNode(object()));
-                    return graph().unique(new LogicNegationNode(isNull));
+                    return TriState.TRUE;
                 }
             } else {
                 if (objectStamp.isExactType()) {
                     // since this type check failed for an exact type we know that it can never
                     // succeed at run time. we also don't care about null values, since they will
                     // also make the check fail.
-                    return LogicConstantNode.contradiction(graph());
+                    return TriState.FALSE;
                 } else {
                     boolean superType = stampType.isAssignableFrom(type());
                     if (!superType && !stampType.isInterface() && !type().isInterface()) {
-                        return LogicConstantNode.contradiction(graph());
+                        return TriState.FALSE;
                     }
                     // since the subtype comparison was only performed on a declared type we don't
                     // really know if it might be true at run time...
                 }
             }
         }
-        return this;
-    }
-
-    public ValueNode object() {
-        return object;
+        return TriState.UNKNOWN;
     }
 
     /**
@@ -121,7 +138,7 @@
 
     @Override
     public void virtualize(VirtualizerTool tool) {
-        State state = tool.getObjectState(object);
+        State state = tool.getObjectState(object());
         if (state != null) {
             tool.replaceWithValue(LogicConstantNode.forBoolean(type().isAssignableFrom(state.getVirtualObject().type()), graph()));
         }
diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/LoadExceptionObjectNode.java
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/LoadExceptionObjectNode.java	Fri Apr 25 16:21:07 2014 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,50 +0,0 @@
-/*
- * Copyright (c) 2009, 2011, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.graal.nodes.java;
-
-import com.oracle.graal.api.code.*;
-import com.oracle.graal.nodes.*;
-import com.oracle.graal.nodes.spi.*;
-import com.oracle.graal.nodes.type.*;
-
-/**
- * Loads an exception object passed by the runtime from a callee to an exception handler in a
- * caller. The node is only produced when lowering an {@link ExceptionObjectNode}.
- * 

- * The frame state upon entry to an exception handler is such that it is a - * {@link BytecodeFrame#rethrowException rethrow exception} state and the stack contains exactly the - * exception object (per the JVM spec) to rethrow. This means that the code generated for this node - * must not cause a deoptimization as the runtime/interpreter would not have a valid location to - * find the exception object to be rethrown. - */ -public class LoadExceptionObjectNode extends AbstractStateSplit implements Lowerable { - - public LoadExceptionObjectNode(Stamp stamp) { - super(stamp); - } - - @Override - public void lower(LoweringTool tool) { - tool.getLowerer().lower(this, tool); - } -} diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/LoadFieldNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/LoadFieldNode.java Fri Apr 25 16:21:07 2014 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/LoadFieldNode.java Mon Apr 28 11:18:15 2014 +0200 @@ -22,11 +22,11 @@ */ package com.oracle.graal.nodes.java; -import java.lang.reflect.*; +import static com.oracle.graal.graph.iterators.NodePredicates.*; import com.oracle.graal.api.meta.*; +import com.oracle.graal.compiler.common.type.*; import com.oracle.graal.graph.*; -import com.oracle.graal.graph.iterators.*; import com.oracle.graal.graph.spi.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.spi.*; @@ -60,7 +60,7 @@ @Override public Node canonical(CanonicalizerTool tool) { - if (usages().isEmpty() && !isVolatile() && (isStatic() || ObjectStamp.isObjectNonNull(object().stamp()))) { + if (usages().isEmpty() && !isVolatile() && (isStatic() || StampTool.isObjectNonNull(object().stamp()))) { return null; } MetaAccessProvider metaAccess = tool.getMetaAccess(); @@ -97,7 +97,7 @@ } private PhiNode asPhi(MetaAccessProvider metaAccess) { - if (!isStatic() && Modifier.isFinal(field.getModifiers()) && object() instanceof ValuePhiNode && ((ValuePhiNode) object()).values().filter(NodePredicates.isNotA(ConstantNode.class)).isEmpty()) { + if (!isStatic() && field.isFinal() && object() instanceof ValuePhiNode && ((ValuePhiNode) object()).values().filter(isNotA(ConstantNode.class)).isEmpty()) { PhiNode phi = (PhiNode) object(); Constant[] constants = new Constant[phi.valueCount()]; for (int i = 0; i < phi.valueCount(); i++) { diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/LoadIndexedNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/LoadIndexedNode.java Fri Apr 25 16:21:07 2014 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/LoadIndexedNode.java Mon Apr 28 11:18:15 2014 +0200 @@ -23,6 +23,7 @@ package com.oracle.graal.nodes.java; import com.oracle.graal.api.meta.*; +import com.oracle.graal.compiler.common.type.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.spi.*; import com.oracle.graal.nodes.type.*; @@ -44,7 +45,7 @@ } private static Stamp createStamp(ValueNode array, Kind kind) { - ResolvedJavaType type = ObjectStamp.typeOrNull(array); + ResolvedJavaType type = StampTool.typeOrNull(array); if (kind == Kind.Object && type != null) { return StampFactory.declared(type.getComponentType()); } else { diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/LoweredAtomicReadAndWriteNode.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/LoweredAtomicReadAndWriteNode.java Mon Apr 28 11:18:15 2014 +0200 @@ -0,0 +1,84 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.graal.nodes.java; + +import com.oracle.graal.api.meta.*; +import com.oracle.graal.graph.*; +import com.oracle.graal.nodes.*; +import com.oracle.graal.nodes.extended.*; +import com.oracle.graal.nodes.spi.*; + +import sun.misc.*; + +/** + * Represents the lowered version of an atomic read-and-write operation like + * {@link Unsafe#getAndSetInt(Object, long, int)} . + */ +@NodeInfo(allowedUsageTypes = {InputType.Memory}) +public class LoweredAtomicReadAndWriteNode extends FixedAccessNode implements StateSplit, LIRLowerable, MemoryCheckpoint.Single { + + @Input private ValueNode newValue; + @Input(InputType.State) private FrameState stateAfter; + + public LoweredAtomicReadAndWriteNode(ValueNode object, LocationNode location, ValueNode newValue, BarrierType barrierType, boolean compressible) { + super(object, location, newValue.stamp(), barrierType, compressible); + this.newValue = newValue; + } + + public FrameState stateAfter() { + return stateAfter; + } + + public void setStateAfter(FrameState x) { + assert x == null || x.isAlive() : "frame state must be in a graph"; + updateUsages(stateAfter, x); + stateAfter = x; + } + + public boolean hasSideEffect() { + return true; + } + + public LocationIdentity getLocationIdentity() { + return location().getLocationIdentity(); + } + + public void generate(NodeLIRBuilderTool gen) { + Value address = location().generateAddress(gen, gen.getLIRGeneratorTool(), gen.operand(object())); + Value result = gen.getLIRGeneratorTool().emitAtomicReadAndWrite(address, gen.operand(newValue)); + gen.setResult(this, result); + } + + public MemoryCheckpoint asMemoryCheckpoint() { + return this; + } + + public MemoryPhiNode asMemoryPhi() { + return null; + } + + public boolean canNullCheck() { + return false; + } + +} diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/LoweredCompareAndSwapNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/LoweredCompareAndSwapNode.java Fri Apr 25 16:21:07 2014 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/LoweredCompareAndSwapNode.java Mon Apr 28 11:18:15 2014 +0200 @@ -23,11 +23,11 @@ package com.oracle.graal.nodes.java; import com.oracle.graal.api.meta.*; +import com.oracle.graal.compiler.common.type.*; import com.oracle.graal.graph.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.extended.*; import com.oracle.graal.nodes.spi.*; -import com.oracle.graal.nodes.type.*; /** * Represents the lowered version of an atomic compare-and-swap operation{@code CompareAndSwapNode}. @@ -80,7 +80,7 @@ @Override public void generate(NodeLIRBuilderTool gen) { assert getNewValue().stamp().isCompatible(getExpectedValue().stamp()); - Value address = location().generateAddress(gen, gen.operand(object())); + Value address = location().generateAddress(gen, gen.getLIRGeneratorTool(), gen.operand(object())); Value result = gen.getLIRGeneratorTool().emitCompareAndSwap(address, gen.operand(getExpectedValue()), gen.operand(getNewValue()), Constant.INT_1, Constant.INT_0); gen.setResult(this, result); } diff -r 3dde8d8c95b8 -r 40d0022115ee 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 Fri Apr 25 16:21:07 2014 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/MethodCallTargetNode.java Mon Apr 28 11:18:15 2014 +0200 @@ -22,9 +22,8 @@ */ package com.oracle.graal.nodes.java; -import java.lang.reflect.*; - import com.oracle.graal.api.meta.*; +import com.oracle.graal.compiler.common.type.*; import com.oracle.graal.graph.*; import com.oracle.graal.graph.spi.*; import com.oracle.graal.nodes.*; @@ -55,7 +54,7 @@ /** * Gets the target method for this invocation instruction. - * + * * @return the target method */ public ResolvedJavaMethod targetMethod() { @@ -76,7 +75,7 @@ /** * Gets the instruction that produces the receiver object for this invocation, if any. - * + * * @return the instruction that produces the receiver object for this invocation if any, * {@code null} if this invocation does not take a receiver object */ @@ -86,7 +85,7 @@ /** * Checks whether this is an invocation of a static method. - * + * * @return {@code true} if the invocation is a static invocation */ public boolean isStatic() { @@ -108,12 +107,12 @@ assertTrue(n instanceof Invoke, "call target can only be used from an invoke (%s)", n); } if (invokeKind == InvokeKind.Special || invokeKind == InvokeKind.Static) { - assertFalse(Modifier.isAbstract(targetMethod.getModifiers()), "special calls or static calls are only allowed for concrete methods (%s)", targetMethod); + assertFalse(targetMethod.isAbstract(), "special calls or static calls are only allowed for concrete methods (%s)", targetMethod); } if (invokeKind == InvokeKind.Static) { - assertTrue(Modifier.isStatic(targetMethod.getModifiers()), "static calls are only allowed for static methods (%s)", targetMethod); + assertTrue(targetMethod.isStatic(), "static calls are only allowed for static methods (%s)", targetMethod); } else { - assertFalse(Modifier.isStatic(targetMethod.getModifiers()), "static calls are only allowed for non-static methods (%s)", targetMethod); + assertFalse(targetMethod.isStatic(), "static calls are only allowed for non-static methods (%s)", targetMethod); } return super.verify(); } @@ -138,18 +137,17 @@ return this; } - // check if the exact type of the receiver can be determined + assert targetMethod.getDeclaringClass().asExactType() == null : "should have been handled by canBeStaticallyBound"; + + // check if the type of the receiver can narrow the result ValueNode receiver = receiver(); - ResolvedJavaType exact = targetMethod.getDeclaringClass().asExactType(); - if (exact == null && ObjectStamp.isExactType(receiver)) { - exact = ObjectStamp.typeOrNull(receiver); - } - if (exact != null) { + ResolvedJavaType type = StampTool.typeOrNull(receiver); + if (type != null) { // either the holder class is exact, or the receiver object has an exact type - ResolvedJavaMethod exactMethod = exact.resolveMethod(targetMethod); - if (exactMethod != null) { + ResolvedJavaMethod resolvedMethod = type.resolveMethod(targetMethod); + if (resolvedMethod != null && (resolvedMethod.canBeStaticallyBound() || StampTool.isExactType(receiver))) { invokeKind = InvokeKind.Special; - targetMethod = exactMethod; + targetMethod = resolvedMethod; return this; } } diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/MonitorExitNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/MonitorExitNode.java Fri Apr 25 16:21:07 2014 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/MonitorExitNode.java Mon Apr 28 11:18:15 2014 +0200 @@ -22,6 +22,7 @@ */ package com.oracle.graal.nodes.java; +import com.oracle.graal.api.code.*; import com.oracle.graal.api.meta.*; import com.oracle.graal.graph.*; import com.oracle.graal.graph.spi.*; @@ -58,7 +59,7 @@ @Override public void simplify(SimplifierTool tool) { - if (escapedReturnValue != null && stateAfter() != null && stateAfter().bci != FrameState.AFTER_BCI) { + if (escapedReturnValue != null && stateAfter() != null && stateAfter().bci != BytecodeFrame.AFTER_BCI) { ValueNode returnValue = escapedReturnValue; setEscapedReturnValue(null); tool.removeIfUnused(returnValue); @@ -74,7 +75,7 @@ public void virtualize(VirtualizerTool tool) { State state = tool.getObjectState(object()); // the monitor exit for a synchronized method should never be virtualized - assert stateAfter().bci != FrameState.AFTER_BCI || state == null; + assert stateAfter().bci != BytecodeFrame.AFTER_BCI || state == null; if (state != null && state.getState() == EscapeState.Virtual && state.getVirtualObject().hasIdentity()) { MonitorIdNode removedLock = state.removeLock(); assert removedLock == getMonitorId() : "mismatch at " + this + ": " + removedLock + " vs. " + getMonitorId(); diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/MonitorIdNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/MonitorIdNode.java Fri Apr 25 16:21:07 2014 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/MonitorIdNode.java Mon Apr 28 11:18:15 2014 +0200 @@ -22,10 +22,10 @@ */ package com.oracle.graal.nodes.java; +import com.oracle.graal.compiler.common.type.*; import com.oracle.graal.graph.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.spi.*; -import com.oracle.graal.nodes.type.*; /** * This node describes one locking scope; it ties the monitor enter, monitor exit and the frame diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/NewArrayNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/NewArrayNode.java Fri Apr 25 16:21:07 2014 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/NewArrayNode.java Mon Apr 28 11:18:15 2014 +0200 @@ -25,6 +25,7 @@ import java.util.*; import com.oracle.graal.api.meta.*; +import com.oracle.graal.compiler.common.type.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.spi.*; import com.oracle.graal.nodes.type.*; @@ -54,7 +55,7 @@ * @return the element type of the array */ public ResolvedJavaType elementType() { - return ObjectStamp.typeOrNull(this).getComponentType(); + return StampTool.typeOrNull(this).getComponentType(); } @Override diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/NewInstanceNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/NewInstanceNode.java Fri Apr 25 16:21:07 2014 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/NewInstanceNode.java Mon Apr 28 11:18:15 2014 +0200 @@ -26,10 +26,10 @@ import java.util.*; import com.oracle.graal.api.meta.*; +import com.oracle.graal.compiler.common.type.*; import com.oracle.graal.graph.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.spi.*; -import com.oracle.graal.nodes.type.*; import com.oracle.graal.nodes.virtual.*; /** diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/NewMultiArrayNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/NewMultiArrayNode.java Fri Apr 25 16:21:07 2014 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/NewMultiArrayNode.java Mon Apr 28 11:18:15 2014 +0200 @@ -23,10 +23,10 @@ package com.oracle.graal.nodes.java; import com.oracle.graal.api.meta.*; +import com.oracle.graal.compiler.common.type.*; import com.oracle.graal.graph.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.spi.*; -import com.oracle.graal.nodes.type.*; /** * The {@code NewMultiArrayNode} represents an allocation of a multi-dimensional object array. diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/RegisterFinalizerNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/RegisterFinalizerNode.java Fri Apr 25 16:21:07 2014 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/RegisterFinalizerNode.java Mon Apr 28 11:18:15 2014 +0200 @@ -24,11 +24,11 @@ import com.oracle.graal.api.code.*; import com.oracle.graal.api.meta.*; +import com.oracle.graal.compiler.common.type.*; import com.oracle.graal.graph.*; import com.oracle.graal.graph.spi.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.spi.*; -import com.oracle.graal.nodes.type.*; /** * This node is used to perform the finalizer registration at the end of the java.lang.Object @@ -53,7 +53,7 @@ @Override public void generate(NodeLIRBuilderTool gen) { ForeignCallLinkage linkage = gen.getLIRGeneratorTool().getForeignCalls().lookupForeignCall(REGISTER_FINALIZER); - gen.getLIRGeneratorTool().emitForeignCall(linkage, this, gen.operand(object())); + gen.getLIRGeneratorTool().emitForeignCall(linkage, gen.state(this), gen.operand(object())); } @Override diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/SelfReplacingMethodCallTargetNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/SelfReplacingMethodCallTargetNode.java Fri Apr 25 16:21:07 2014 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/SelfReplacingMethodCallTargetNode.java Mon Apr 28 11:18:15 2014 +0200 @@ -22,9 +22,8 @@ */ package com.oracle.graal.nodes.java; -import java.lang.reflect.*; - import com.oracle.graal.api.meta.*; +import com.oracle.graal.compiler.common.*; import com.oracle.graal.graph.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.spi.*; @@ -65,7 +64,7 @@ @Override public void lower(LoweringTool tool) { - InvokeKind invokeKind = Modifier.isStatic(replacementTargetMethod.getModifiers()) ? InvokeKind.Static : InvokeKind.Special; + InvokeKind invokeKind = replacementTargetMethod.isStatic() ? InvokeKind.Static : InvokeKind.Special; MethodCallTargetNode replacement = graph().add( new MethodCallTargetNode(invokeKind, replacementTargetMethod, replacementArguments.toArray(new ValueNode[replacementArguments.size()]), replacementReturnType)); diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/StoreFieldNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/StoreFieldNode.java Fri Apr 25 16:21:07 2014 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/StoreFieldNode.java Mon Apr 28 11:18:15 2014 +0200 @@ -23,10 +23,10 @@ package com.oracle.graal.nodes.java; import com.oracle.graal.api.meta.*; +import com.oracle.graal.compiler.common.type.*; import com.oracle.graal.graph.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.spi.*; -import com.oracle.graal.nodes.type.*; import com.oracle.graal.nodes.virtual.*; /** diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/StoreIndexedNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/StoreIndexedNode.java Fri Apr 25 16:21:07 2014 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/StoreIndexedNode.java Mon Apr 28 11:18:15 2014 +0200 @@ -23,6 +23,7 @@ package com.oracle.graal.nodes.java; import com.oracle.graal.api.meta.*; +import com.oracle.graal.compiler.common.type.*; import com.oracle.graal.graph.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.spi.*; @@ -75,8 +76,8 @@ int index = indexValue.isConstant() ? indexValue.asConstant().asInt() : -1; if (index >= 0 && index < arrayState.getVirtualObject().entryCount()) { ResolvedJavaType componentType = arrayState.getVirtualObject().type().getComponentType(); - if (componentType.isPrimitive() || ObjectStamp.isObjectAlwaysNull(value) || componentType.getSuperclass() == null || - (ObjectStamp.typeOrNull(value) != null && componentType.isAssignableFrom(ObjectStamp.typeOrNull(value)))) { + if (componentType.isPrimitive() || StampTool.isObjectAlwaysNull(value) || componentType.getSuperclass() == null || + (StampTool.typeOrNull(value) != null && componentType.isAssignableFrom(StampTool.typeOrNull(value)))) { tool.setVirtualEntry(arrayState, index, value(), false); tool.delete(); } diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/TypeSwitchNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/TypeSwitchNode.java Fri Apr 25 16:21:07 2014 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/TypeSwitchNode.java Mon Apr 28 11:18:15 2014 +0200 @@ -26,11 +26,11 @@ import com.oracle.graal.api.meta.*; import com.oracle.graal.api.meta.ResolvedJavaType.Representation; +import com.oracle.graal.compiler.common.type.*; import com.oracle.graal.graph.spi.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.extended.*; import com.oracle.graal.nodes.spi.*; -import com.oracle.graal.nodes.type.*; import com.oracle.graal.nodes.util.*; /** @@ -51,7 +51,7 @@ * @param keyProbabilities the probabilities of the keys * @param keySuccessors the successor index for each key */ - public TypeSwitchNode(ValueNode value, AbstractBeginNode[] successors, ResolvedJavaType[] keys, double[] keyProbabilities, int[] keySuccessors) { + public TypeSwitchNode(ValueNode value, BeginNode[] successors, ResolvedJavaType[] keys, double[] keyProbabilities, int[] keySuccessors) { super(value, successors, keySuccessors, keyProbabilities); assert successors.length <= keys.length + 1; assert keySuccessors.length == keyProbabilities.length; @@ -134,7 +134,7 @@ tool.addToWorkList(defaultSuccessor()); graph().removeSplitPropagate(this, defaultSuccessor()); } else if (validKeys != keys.length) { - ArrayList newSuccessors = new ArrayList<>(blockSuccessorCount()); + ArrayList newSuccessors = new ArrayList<>(blockSuccessorCount()); ResolvedJavaType[] newKeys = new ResolvedJavaType[validKeys]; int[] newKeySuccessors = new int[validKeys + 1]; double[] newKeyProbabilities = new double[validKeys + 1]; @@ -167,14 +167,14 @@ } for (int i = 0; i < blockSuccessorCount(); i++) { - AbstractBeginNode successor = blockSuccessor(i); + BeginNode successor = blockSuccessor(i); if (!newSuccessors.contains(successor)) { tool.deleteBranch(successor); } setBlockSuccessor(i, null); } - AbstractBeginNode[] successorsArray = newSuccessors.toArray(new AbstractBeginNode[newSuccessors.size()]); + BeginNode[] successorsArray = newSuccessors.toArray(new BeginNode[newSuccessors.size()]); TypeSwitchNode newSwitch = graph().add(new TypeSwitchNode(value(), successorsArray, newKeys, newKeyProbabilities, newKeySuccessors)); ((FixedWithNextNode) predecessor()).setNext(newSwitch); GraphUtil.killWithUnusedFloatingInputs(this); diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/spi/ArithmeticLIRGenerator.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/spi/ArithmeticLIRGenerator.java Fri Apr 25 16:21:07 2014 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,102 +0,0 @@ -/* - * 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.nodes.spi; - -import com.oracle.graal.api.meta.*; -import com.oracle.graal.nodes.*; -import com.oracle.graal.nodes.calc.FloatConvertNode.FloatConvert; -import com.oracle.graal.nodes.type.*; - -/** - * This interface can be used to generate LIR for arithmetic operations. - */ -public interface ArithmeticLIRGenerator { - /** - * TODO remove reference to {@link Stamp}. - */ - PlatformKind getPlatformKind(Stamp stamp); - - Value emitNegate(Value input); - - Value emitAdd(Value a, Value b); - - Value emitSub(Value a, Value b); - - Value emitMul(Value a, Value b); - - /** - * TODO remove {@link DeoptimizeNode}. - */ - Value emitDiv(Value a, Value b, DeoptimizingNode deopting); - - /** - * TODO remove {@link DeoptimizeNode}. - */ - Value emitRem(Value a, Value b, DeoptimizingNode deopting); - - /** - * TODO remove {@link DeoptimizeNode}. - */ - Value emitUDiv(Value a, Value b, DeoptimizingNode deopting); - - /** - * TODO remove {@link DeoptimizeNode}. - */ - Value emitURem(Value a, Value b, DeoptimizingNode deopting); - - Value emitNot(Value input); - - Value emitAnd(Value a, Value b); - - Value emitOr(Value a, Value b); - - Value emitXor(Value a, Value b); - - Value emitShl(Value a, Value b); - - Value emitShr(Value a, Value b); - - Value emitUShr(Value a, Value b); - - Value emitFloatConvert(FloatConvert op, Value inputVal); - - Value emitReinterpret(PlatformKind to, Value inputVal); - - Value emitNarrow(Value inputVal, int bits); - - Value emitSignExtend(Value inputVal, int fromBits, int toBits); - - Value emitZeroExtend(Value inputVal, int fromBits, int toBits); - - Value emitMathAbs(Value input); - - Value emitMathSqrt(Value input); - - Value emitMathLog(Value input, boolean base10); - - Value emitMathCos(Value input); - - Value emitMathSin(Value input); - - Value emitMathTan(Value input); -} diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/spi/ArithmeticLIRLowerable.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/spi/ArithmeticLIRLowerable.java Fri Apr 25 16:21:07 2014 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/spi/ArithmeticLIRLowerable.java Mon Apr 28 11:18:15 2014 +0200 @@ -23,8 +23,9 @@ package com.oracle.graal.nodes.spi; import com.oracle.graal.api.code.*; +import com.oracle.graal.lir.gen.*; public interface ArithmeticLIRLowerable extends ArithmeticOperation { - void generate(NodeLIRBuilderTool gen); + void generate(NodeMappableLIRBuilder builder, ArithmeticLIRGenerator gen); } diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/spi/LIRGeneratorTool.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/spi/LIRGeneratorTool.java Fri Apr 25 16:21:07 2014 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,99 +0,0 @@ -/* - * Copyright (c) 2011, 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.nodes.spi; - -import com.oracle.graal.api.code.*; -import com.oracle.graal.api.meta.*; -import com.oracle.graal.nodes.*; -import com.oracle.graal.nodes.extended.*; - -public interface LIRGeneratorTool extends ArithmeticLIRGenerator { - - TargetDescription target(); - - MetaAccessProvider getMetaAccess(); - - CodeCacheProvider getCodeCache(); - - ForeignCallsProvider getForeignCalls(); - - Value emitLoad(PlatformKind kind, Value address, Access access); - - void emitStore(PlatformKind kind, Value address, Value input, Access access); - - Value emitCompareAndSwap(Value address, Value expectedValue, Value newValue, Value trueValue, Value falseValue); - - void emitDeoptimize(Value actionAndReason, Value failedSpeculation, DeoptimizingNode deopting); - - Value emitForeignCall(ForeignCallLinkage linkage, DeoptimizingNode info, Value... args); - - /** - * Checks whether the supplied constant can be used without loading it into a register for most - * operations, i.e., for commonly used arithmetic, logical, and comparison operations. - * - * @param c The constant to check. - * @return True if the constant can be used directly, false if the constant needs to be in a - * register. - */ - boolean canInlineConstant(Constant c); - - boolean canStoreConstant(Constant c, boolean isCompressed); - - RegisterAttributes attributes(Register register); - - AllocatableValue newVariable(PlatformKind kind); - - AllocatableValue emitMove(Value input); - - void emitMove(AllocatableValue dst, Value src); - - /** - * Emits an op that loads the address of some raw data. - * - * @param dst the variable into which the address is loaded - * @param data the data to be installed with the generated code - */ - void emitData(AllocatableValue dst, byte[] data); - - Value emitAddress(Value base, long displacement, Value index, int scale); - - Value emitAddress(StackSlot slot); - - void emitMembar(int barriers); - - void emitUnwind(Value operand); - - /** - * Called just before register allocation is performed on the LIR owned by this generator. - * Overriding implementations of this method must call the overridden method. - */ - void beforeRegisterAllocation(); - - void emitIncomingValues(Value[] params); - - /** - * Emits a return instruction. Implementations need to insert a move if the input is not in the - * correct location. - */ - void emitReturn(Value input); -} diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/spi/LIRTypeTool.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/spi/LIRTypeTool.java Fri Apr 25 16:21:07 2014 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,37 +0,0 @@ -/* - * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -package com.oracle.graal.nodes.spi; - -import com.oracle.graal.api.meta.*; - -/** - * This interface can be used to access platform and VM specific kinds. - */ -public interface LIRTypeTool { - - PlatformKind getIntegerKind(int bits, boolean unsigned); - - PlatformKind getFloatingKind(int bits); - - PlatformKind getObjectKind(); -} diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/spi/Lowerable.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/spi/Lowerable.java Fri Apr 25 16:21:07 2014 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/spi/Lowerable.java Mon Apr 28 11:18:15 2014 +0200 @@ -22,13 +22,14 @@ */ package com.oracle.graal.nodes.spi; +import com.oracle.graal.graph.*; import com.oracle.graal.nodes.*; /** * Interface implemented by nodes that can replace themselves with lower level nodes during a phase * that transforms a graph to replace higher level nodes with lower level nodes. */ -public interface Lowerable { +public interface Lowerable extends NodeInterface { /** * Expand this node into lower level nodes expressing the same semantics. If the introduced diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/spi/MemoryArithmeticLIRLowerer.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/spi/MemoryArithmeticLIRLowerer.java Fri Apr 25 16:21:07 2014 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/spi/MemoryArithmeticLIRLowerer.java Mon Apr 28 11:18:15 2014 +0200 @@ -25,10 +25,10 @@ import java.util.*; import com.oracle.graal.api.meta.*; +import com.oracle.graal.compiler.common.calc.*; +import com.oracle.graal.compiler.common.type.*; import com.oracle.graal.nodes.*; -import com.oracle.graal.nodes.calc.FloatConvertNode.FloatConvert; import com.oracle.graal.nodes.extended.*; -import com.oracle.graal.nodes.type.*; /** * This interface can be used to generate LIR for arithmetic operations where one of the operations diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/spi/NodeLIRBuilderTool.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/spi/NodeLIRBuilderTool.java Fri Apr 25 16:21:07 2014 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/spi/NodeLIRBuilderTool.java Mon Apr 28 11:18:15 2014 +0200 @@ -26,12 +26,19 @@ import com.oracle.graal.api.code.*; import com.oracle.graal.api.meta.*; +import com.oracle.graal.compiler.common.cfg.*; +import com.oracle.graal.lir.*; +import com.oracle.graal.lir.gen.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.calc.*; +import com.oracle.graal.nodes.cfg.*; import com.oracle.graal.nodes.extended.*; public interface NodeLIRBuilderTool extends NodeMappableLIRBuilder { + // TODO (je) remove and move into the Node + LIRFrameState state(DeoptimizingNode deopt); + void emitNullCheck(ValueNode v, DeoptimizingNode deopting); void emitIf(IfNode i); @@ -59,9 +66,19 @@ LIRGeneratorTool getLIRGeneratorTool(); - void emitOverflowCheckBranch(AbstractBeginNode overflowSuccessor, AbstractBeginNode next, double probability); + void emitOverflowCheckBranch(BeginNode overflowSuccessor, BeginNode next, double probability); Value[] visitInvokeArguments(CallingConvention cc, Collection arguments); MemoryArithmeticLIRLowerer getMemoryLowerer(); + + Variable newVariable(Kind kind); + + void emitArrayEquals(Kind kind, Variable result, Value array1, Value array2, Value length); + + void emitBitCount(Variable result, Value operand); + + void emitBitScanForward(Variable result, Value operand); + + void doBlock(Block block, StructuredGraph graph, BlockMap> blockMap); } diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/spi/NodeWithState.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/spi/NodeWithState.java Fri Apr 25 16:21:07 2014 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/spi/NodeWithState.java Mon Apr 28 11:18:15 2014 +0200 @@ -23,12 +23,15 @@ package com.oracle.graal.nodes.spi; import com.oracle.graal.graph.*; +import com.oracle.graal.graph.iterators.*; import com.oracle.graal.nodes.*; /** * Interface for nodes which have {@link FrameState} nodes as input. */ -public interface NodeWithState { +public interface NodeWithState extends NodeInterface { - Node asNode(); + default NodeIterable states() { + return asNode().inputs().filter(FrameState.class); + } } diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/spi/ReplacementsProvider.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/spi/ReplacementsProvider.java Fri Apr 25 16:21:07 2014 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/spi/ReplacementsProvider.java Mon Apr 28 11:18:15 2014 +0200 @@ -24,11 +24,12 @@ import com.oracle.graal.api.code.*; import com.oracle.graal.api.meta.*; +import com.oracle.graal.api.replacements.*; /** * Interface for service providers that register replacements with the compiler. */ public interface ReplacementsProvider { - void registerReplacements(MetaAccessProvider metaAccess, LoweringProvider lowerer, Replacements replacements, TargetDescription target); + void registerReplacements(MetaAccessProvider metaAccess, LoweringProvider lowerer, SnippetReflectionProvider snippetReflection, Replacements replacements, TargetDescription target); } diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/type/FloatStamp.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/type/FloatStamp.java Fri Apr 25 16:21:07 2014 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,234 +0,0 @@ -/* - * Copyright (c) 2012, 2014, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -package com.oracle.graal.nodes.type; - -import com.oracle.graal.api.meta.*; -import com.oracle.graal.graph.*; -import com.oracle.graal.nodes.spi.*; - -public class FloatStamp extends PrimitiveStamp { - - private final double lowerBound; - private final double upperBound; - private final boolean nonNaN; - - protected FloatStamp(int bits) { - this(bits, Double.NEGATIVE_INFINITY, Double.POSITIVE_INFINITY, false); - } - - protected FloatStamp(int bits, double lowerBound, double upperBound, boolean nonNaN) { - super(bits); - this.lowerBound = lowerBound; - this.upperBound = upperBound; - this.nonNaN = nonNaN; - } - - @Override - public Stamp unrestricted() { - return new FloatStamp(getBits()); - } - - @Override - public Stamp illegal() { - return new FloatStamp(getBits(), Double.POSITIVE_INFINITY, Double.NEGATIVE_INFINITY, true); - } - - @Override - public boolean isLegal() { - return lowerBound <= upperBound || !nonNaN; - } - - @Override - public Kind getStackKind() { - if (getBits() > 32) { - return Kind.Double; - } else { - return Kind.Float; - } - } - - @Override - public PlatformKind getPlatformKind(LIRTypeTool tool) { - return tool.getFloatingKind(getBits()); - } - - @Override - public ResolvedJavaType javaType(MetaAccessProvider metaAccess) { - switch (getBits()) { - case 32: - return metaAccess.lookupJavaType(Float.TYPE); - case 64: - return metaAccess.lookupJavaType(Double.TYPE); - default: - throw GraalInternalError.shouldNotReachHere(); - } - } - - /** - * The (inclusive) lower bound on the value described by this stamp. - */ - public double lowerBound() { - return lowerBound; - } - - /** - * The (inclusive) upper bound on the value described by this stamp. - */ - public double upperBound() { - return upperBound; - } - - public boolean isNonNaN() { - return nonNaN; - } - - public boolean isUnrestricted() { - return lowerBound == Double.NEGATIVE_INFINITY && upperBound == Double.POSITIVE_INFINITY && !nonNaN; - } - - public boolean contains(double value) { - if (Double.isNaN(value)) { - return !nonNaN; - } else { - return value >= lowerBound && value <= upperBound; - } - } - - @Override - public String toString() { - StringBuilder str = new StringBuilder(); - str.append('f'); - str.append(getBits()); - str.append(nonNaN ? "!" : ""); - if (lowerBound == upperBound) { - str.append(" [").append(lowerBound).append(']'); - } else if (lowerBound != Double.NEGATIVE_INFINITY || upperBound != Double.POSITIVE_INFINITY) { - str.append(" [").append(lowerBound).append(" - ").append(upperBound).append(']'); - } - return str.toString(); - } - - @Override - public Stamp meet(Stamp otherStamp) { - if (otherStamp == this) { - return this; - } - if (!(otherStamp instanceof FloatStamp)) { - return StampFactory.illegal(Kind.Illegal); - } - FloatStamp other = (FloatStamp) otherStamp; - assert getBits() == other.getBits(); - double meetUpperBound = Math.max(upperBound, other.upperBound); - double meetLowerBound = Math.min(lowerBound, other.lowerBound); - boolean meetNonNaN = nonNaN && other.nonNaN; - if (meetLowerBound == lowerBound && meetUpperBound == upperBound && meetNonNaN == nonNaN) { - return this; - } else if (meetLowerBound == other.lowerBound && meetUpperBound == other.upperBound && meetNonNaN == other.nonNaN) { - return other; - } else { - return new FloatStamp(getBits(), meetLowerBound, meetUpperBound, meetNonNaN); - } - } - - @Override - public Stamp join(Stamp otherStamp) { - if (otherStamp == this) { - return this; - } - if (!(otherStamp instanceof FloatStamp)) { - return StampFactory.illegal(Kind.Illegal); - } - FloatStamp other = (FloatStamp) otherStamp; - assert getBits() == other.getBits(); - double joinUpperBound = Math.min(upperBound, other.upperBound); - double joinLowerBound = Math.max(lowerBound, other.lowerBound); - boolean joinNonNaN = nonNaN || other.nonNaN; - if (joinLowerBound == lowerBound && joinUpperBound == upperBound && joinNonNaN == nonNaN) { - return this; - } else if (joinLowerBound == other.lowerBound && joinUpperBound == other.upperBound && joinNonNaN == other.nonNaN) { - return other; - } else { - return new FloatStamp(getBits(), joinLowerBound, joinUpperBound, joinNonNaN); - } - } - - @Override - public int hashCode() { - final int prime = 31; - int result = 1; - long temp; - result = prime * result + super.hashCode(); - temp = Double.doubleToLongBits(lowerBound); - result = prime * result + (int) (temp ^ (temp >>> 32)); - result = prime * result + (nonNaN ? 1231 : 1237); - temp = Double.doubleToLongBits(upperBound); - result = prime * result + (int) (temp ^ (temp >>> 32)); - return result; - } - - @Override - public boolean isCompatible(Stamp stamp) { - if (this == stamp) { - return true; - } - if (stamp instanceof FloatStamp) { - FloatStamp other = (FloatStamp) stamp; - return getBits() == other.getBits(); - } - return false; - } - - @Override - public boolean equals(Object obj) { - if (this == obj) { - return true; - } - if (obj == null || getClass() != obj.getClass() || !super.equals(obj)) { - return false; - } - FloatStamp other = (FloatStamp) obj; - if (Double.doubleToLongBits(lowerBound) != Double.doubleToLongBits(other.lowerBound)) { - return false; - } - if (Double.doubleToLongBits(upperBound) != Double.doubleToLongBits(other.upperBound)) { - return false; - } - if (nonNaN != other.nonNaN) { - return false; - } - return true; - } - - @Override - public Constant asConstant() { - if (nonNaN && lowerBound == upperBound) { - switch (getBits()) { - case 32: - return Constant.forFloat((float) lowerBound); - case 64: - return Constant.forDouble(lowerBound); - } - } - return null; - } -} diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/type/IllegalStamp.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/type/IllegalStamp.java Fri Apr 25 16:21:07 2014 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,92 +0,0 @@ -/* - * Copyright (c) 2012, 2014, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -package com.oracle.graal.nodes.type; - -import com.oracle.graal.api.meta.*; -import com.oracle.graal.graph.*; -import com.oracle.graal.nodes.spi.*; - -/** - * This stamp represents the illegal type. Values with this type can not exist at run time. - */ -public final class IllegalStamp extends Stamp { - - private IllegalStamp() { - } - - @Override - public Kind getStackKind() { - return Kind.Illegal; - } - - @Override - public PlatformKind getPlatformKind(LIRTypeTool tool) { - throw GraalInternalError.shouldNotReachHere("illegal stamp should not reach backend"); - } - - @Override - public Stamp unrestricted() { - return this; - } - - @Override - public Stamp illegal() { - return this; - } - - @Override - public ResolvedJavaType javaType(MetaAccessProvider metaAccess) { - throw GraalInternalError.shouldNotReachHere("illegal stamp has no Java type"); - } - - @Override - public Stamp meet(Stamp other) { - return this; - } - - @Override - public Stamp join(Stamp other) { - return this; - } - - @Override - public boolean isCompatible(Stamp stamp) { - return false; - } - - @Override - public String toString() { - return "ILLEGAL"; - } - - @Override - public boolean isLegal() { - return false; - } - - private static IllegalStamp instance = new IllegalStamp(); - - static IllegalStamp getInstance() { - return instance; - } -} diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/type/IntegerStamp.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/type/IntegerStamp.java Fri Apr 25 16:21:07 2014 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,348 +0,0 @@ -/* - * Copyright (c) 2012, 2014, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -package com.oracle.graal.nodes.type; - -import java.util.*; - -import com.oracle.graal.api.meta.*; -import com.oracle.graal.graph.*; -import com.oracle.graal.nodes.*; -import com.oracle.graal.nodes.spi.*; - -/** - * Describes the possible values of a {@link ValueNode} that produces an int or long result. - * - * The description consists of (inclusive) lower and upper bounds and up (may be set) and down - * (always set) bit-masks. - */ -public class IntegerStamp extends PrimitiveStamp { - - private final boolean unsigned; - - private final long lowerBound; - private final long upperBound; - private final long downMask; - private final long upMask; - - public IntegerStamp(int bits, boolean unsigned, long lowerBound, long upperBound, long downMask, long upMask) { - super(bits); - this.unsigned = unsigned; - this.lowerBound = lowerBound; - this.upperBound = upperBound; - this.downMask = downMask; - this.upMask = upMask; - assert lowerBound >= defaultMinValue(bits, unsigned) : this; - assert upperBound <= defaultMaxValue(bits, unsigned) : this; - assert (downMask & defaultMask(bits)) == downMask : this; - assert (upMask & defaultMask(bits)) == upMask : this; - } - - @Override - public Stamp unrestricted() { - return new IntegerStamp(getBits(), unsigned, defaultMinValue(getBits(), unsigned), defaultMaxValue(getBits(), unsigned), 0, defaultMask(getBits())); - } - - @Override - public Stamp illegal() { - return new IntegerStamp(getBits(), unsigned, defaultMaxValue(getBits(), unsigned), defaultMinValue(getBits(), unsigned), defaultMask(getBits()), 0); - } - - @Override - public boolean isLegal() { - if (unsigned) { - return Long.compareUnsigned(lowerBound, upperBound) <= 0; - } else { - return lowerBound <= upperBound; - } - } - - @Override - public Kind getStackKind() { - if (getBits() > 32) { - return Kind.Long; - } else { - return Kind.Int; - } - } - - @Override - public PlatformKind getPlatformKind(LIRTypeTool tool) { - return tool.getIntegerKind(getBits(), unsigned); - } - - @Override - public ResolvedJavaType javaType(MetaAccessProvider metaAccess) { - switch (getBits()) { - case 1: - assert unsigned; - return metaAccess.lookupJavaType(Boolean.TYPE); - case 8: - assert !unsigned; - return metaAccess.lookupJavaType(Byte.TYPE); - case 16: - if (unsigned) { - return metaAccess.lookupJavaType(Character.TYPE); - } else { - return metaAccess.lookupJavaType(Short.TYPE); - } - case 32: - assert !unsigned; - return metaAccess.lookupJavaType(Integer.TYPE); - case 64: - assert !unsigned; - return metaAccess.lookupJavaType(Long.TYPE); - default: - throw GraalInternalError.shouldNotReachHere(); - } - } - - /** - * Check whether the value described by this stamp is unsigned. - */ - public boolean isUnsigned() { - return unsigned; - } - - /** - * The (inclusive) lower bound on the value described by this stamp. - */ - public long lowerBound() { - return lowerBound; - } - - /** - * The (inclusive) upper bound on the value described by this stamp. - */ - public long upperBound() { - return upperBound; - } - - /** - * This bit-mask describes the bits that are always set in the value described by this stamp. - */ - public long downMask() { - return downMask; - } - - /** - * This bit-mask describes the bits that can be set in the value described by this stamp. - */ - public long upMask() { - return upMask; - } - - public boolean isUnrestricted() { - return lowerBound == defaultMinValue(getBits(), unsigned) && upperBound == defaultMaxValue(getBits(), unsigned) && downMask == 0 && upMask == defaultMask(getBits()); - } - - public boolean contains(long value) { - return value >= lowerBound && value <= upperBound && (value & downMask) == downMask && (value & upMask) == (value & defaultMask(getBits())); - } - - public boolean isPositive() { - return lowerBound() >= 0; - } - - public boolean isNegative() { - return upperBound() <= 0; - } - - public boolean isStrictlyPositive() { - return lowerBound() > 0; - } - - public boolean isStrictlyNegative() { - return upperBound() < 0; - } - - public boolean canBePositive() { - return upperBound() > 0; - } - - public boolean canBeNegative() { - return lowerBound() < 0; - } - - @Override - public String toString() { - StringBuilder str = new StringBuilder(); - str.append(unsigned ? 'u' : 'i'); - str.append(getBits()); - if (lowerBound == upperBound) { - str.append(" [").append(lowerBound).append(']'); - } else if (lowerBound != defaultMinValue(getBits(), unsigned) || upperBound != defaultMaxValue(getBits(), unsigned)) { - str.append(" [").append(lowerBound).append(" - ").append(upperBound).append(']'); - } - if (downMask != 0) { - str.append(" \u21ca"); - new Formatter(str).format("%016x", downMask); - } - if (upMask != defaultMask(getBits())) { - str.append(" \u21c8"); - new Formatter(str).format("%016x", upMask); - } - return str.toString(); - } - - private Stamp createStamp(IntegerStamp other, long newUpperBound, long newLowerBound, long newDownMask, long newUpMask) { - assert getBits() == other.getBits() && unsigned == other.unsigned; - if (newLowerBound > newUpperBound || (newDownMask & (~newUpMask)) != 0) { - return illegal(); - } else if (newLowerBound == lowerBound && newUpperBound == upperBound && newDownMask == downMask && newUpMask == upMask) { - return this; - } else if (newLowerBound == other.lowerBound && newUpperBound == other.upperBound && newDownMask == other.downMask && newUpMask == other.upMask) { - return other; - } else { - return new IntegerStamp(getBits(), unsigned, newLowerBound, newUpperBound, newDownMask, newUpMask); - } - } - - @Override - public Stamp meet(Stamp otherStamp) { - if (otherStamp == this) { - return this; - } - if (!(otherStamp instanceof IntegerStamp)) { - return StampFactory.illegal(Kind.Illegal); - } - IntegerStamp other = (IntegerStamp) otherStamp; - return createStamp(other, Math.max(upperBound, other.upperBound), Math.min(lowerBound, other.lowerBound), downMask & other.downMask, upMask | other.upMask); - } - - @Override - public Stamp join(Stamp otherStamp) { - if (otherStamp == this) { - return this; - } - if (!(otherStamp instanceof IntegerStamp)) { - return StampFactory.illegal(Kind.Illegal); - } - IntegerStamp other = (IntegerStamp) otherStamp; - long newDownMask = downMask | other.downMask; - long newLowerBound = Math.max(lowerBound, other.lowerBound) | newDownMask; - return createStamp(other, Math.min(upperBound, other.upperBound), newLowerBound, newDownMask, upMask & other.upMask); - } - - @Override - public boolean isCompatible(Stamp stamp) { - if (this == stamp) { - return true; - } - if (stamp instanceof IntegerStamp) { - IntegerStamp other = (IntegerStamp) stamp; - return getBits() == other.getBits() && unsigned == other.unsigned; - } - return false; - } - - @Override - public int hashCode() { - final int prime = 31; - int result = 1; - result = prime * result + super.hashCode(); - result = prime * result + (int) (lowerBound ^ (lowerBound >>> 32)); - result = prime * result + (int) (upperBound ^ (upperBound >>> 32)); - result = prime * result + (int) (downMask ^ (downMask >>> 32)); - result = prime * result + (int) (upMask ^ (upMask >>> 32)); - return result; - } - - @Override - public boolean equals(Object obj) { - if (this == obj) { - return true; - } - if (obj == null || getClass() != obj.getClass() || !super.equals(obj)) { - return false; - } - IntegerStamp other = (IntegerStamp) obj; - if (lowerBound != other.lowerBound || upperBound != other.upperBound || downMask != other.downMask || upMask != other.upMask) { - return false; - } - return true; - } - - public static long defaultMask(int bits) { - assert 0 < bits && bits <= 64; - if (bits == 64) { - return 0xffffffffffffffffL; - } else { - return (1L << bits) - 1; - } - } - - public static long defaultMinValue(int bits, boolean unsigned) { - if (unsigned) { - return 0; - } else { - return -1L << (bits - 1); - } - } - - public static long defaultMaxValue(int bits, boolean unsigned) { - return defaultMask(unsigned ? bits : bits - 1); - } - - public static long upMaskFor(int bits, long lowerBound, long upperBound) { - long mask = lowerBound | upperBound; - if (mask == 0) { - return 0; - } else { - return ((-1L) >>> Long.numberOfLeadingZeros(mask)) & defaultMask(bits); - } - } - - /** - * Checks if the 2 stamps represent values of the same sign. Returns true if the two stamps are - * both positive of null or if they are both strictly negative - * - * @return true if the two stamps are both positive of null or if they are both strictly - * negative - */ - public static boolean sameSign(IntegerStamp s1, IntegerStamp s2) { - return s1.isPositive() && s2.isPositive() || s1.isStrictlyNegative() && s2.isStrictlyNegative(); - } - - @Override - public Constant asConstant() { - if (lowerBound == upperBound) { - switch (getBits()) { - case 1: - return Constant.forBoolean(lowerBound != 0); - case 8: - return Constant.forByte((byte) lowerBound); - case 16: - if (unsigned) { - return Constant.forChar((char) lowerBound); - } else { - return Constant.forShort((short) lowerBound); - } - case 32: - return Constant.forInt((int) lowerBound); - case 64: - return Constant.forLong(lowerBound); - } - } - return null; - } -} diff -r 3dde8d8c95b8 -r 40d0022115ee 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 Fri Apr 25 16:21:07 2014 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,336 +0,0 @@ -/* - * Copyright (c) 2012, 2014, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -package com.oracle.graal.nodes.type; - -import java.lang.reflect.*; -import java.util.*; - -import com.oracle.graal.api.meta.*; -import com.oracle.graal.nodes.*; -import com.oracle.graal.nodes.spi.*; - -public class ObjectStamp extends Stamp { - - private final ResolvedJavaType type; - private final boolean exactType; - private final boolean nonNull; - private final boolean alwaysNull; - - public ObjectStamp(ResolvedJavaType type, boolean exactType, boolean nonNull, boolean alwaysNull) { - this.type = type; - this.exactType = exactType; - this.nonNull = nonNull; - this.alwaysNull = alwaysNull; - } - - @Override - public Stamp unrestricted() { - return StampFactory.object(); - } - - @Override - public Stamp illegal() { - return new ObjectStamp(null, true, true, false); - } - - @Override - public boolean isLegal() { - return !exactType || (type != null && (isConcreteType(type))); - } - - @Override - public Kind getStackKind() { - return Kind.Object; - } - - @Override - public PlatformKind getPlatformKind(LIRTypeTool tool) { - return tool.getObjectKind(); - } - - @Override - public ResolvedJavaType javaType(MetaAccessProvider metaAccess) { - if (type != null) { - return type; - } - return metaAccess.lookupJavaType(Object.class); - } - - public boolean nonNull() { - return nonNull; - } - - public boolean alwaysNull() { - return alwaysNull; - } - - public ResolvedJavaType type() { - return type; - } - - public boolean isExactType() { - return exactType; - } - - @Override - public String toString() { - StringBuilder str = new StringBuilder(); - str.append('a'); - str.append(nonNull ? "!" : "").append(exactType ? "#" : "").append(' ').append(type == null ? "-" : type.getName()).append(alwaysNull ? " NULL" : ""); - return str.toString(); - } - - @Override - public Stamp meet(Stamp otherStamp) { - if (this == otherStamp) { - return this; - } - if (!(otherStamp instanceof ObjectStamp)) { - return StampFactory.illegal(Kind.Illegal); - } - ObjectStamp other = (ObjectStamp) otherStamp; - ResolvedJavaType meetType; - boolean meetExactType; - boolean meetNonNull; - boolean meetAlwaysNull; - if (other.alwaysNull) { - meetType = type(); - meetExactType = exactType; - meetNonNull = false; - meetAlwaysNull = alwaysNull; - } else if (alwaysNull) { - meetType = other.type(); - meetExactType = other.exactType; - meetNonNull = false; - meetAlwaysNull = other.alwaysNull; - } else { - meetType = meetTypes(type(), other.type()); - meetExactType = exactType && other.exactType; - if (meetExactType && type != null && other.type != null) { - // meeting two valid exact types may result in a non-exact type - meetExactType = Objects.equals(meetType, type) && Objects.equals(meetType, other.type); - } - meetNonNull = nonNull && other.nonNull; - meetAlwaysNull = false; - } - - if (Objects.equals(meetType, type) && meetExactType == exactType && meetNonNull == nonNull && meetAlwaysNull == alwaysNull) { - return this; - } else if (Objects.equals(meetType, other.type) && meetExactType == other.exactType && meetNonNull == other.nonNull && meetAlwaysNull == other.alwaysNull) { - return other; - } else { - return new ObjectStamp(meetType, meetExactType, meetNonNull, meetAlwaysNull); - } - } - - @Override - public Stamp join(Stamp otherStamp) { - return join0(otherStamp, false); - } - - @Override - public boolean isCompatible(Stamp other) { - if (this == other) { - return true; - } - if (other instanceof ObjectStamp) { - return true; - } - return false; - } - - /** - * Returns the stamp representing the type of this stamp after a cast to the type represented by - * the {@code to} stamp. While this is very similar to a {@link #join} operation, in the case - * where both types are not obviously related, the cast operation will prefer the type of the - * {@code to} stamp. This is necessary as long as ObjectStamps are not able to accurately - * represent intersection types. - * - * For example when joining the {@link RandomAccess} type with the {@link AbstractList} type, - * without intersection types, this would result in the most generic type ({@link Object} ). For - * this reason, in some cases a {@code castTo} operation is preferable in order to keep at least - * the {@link AbstractList} type. - * - * @param to the stamp this stamp should be casted to - * @return This stamp casted to the {@code to} stamp - */ - public Stamp castTo(ObjectStamp to) { - return join0(to, true); - } - - private Stamp join0(Stamp otherStamp, boolean castToOther) { - if (this == otherStamp) { - return this; - } - if (!(otherStamp instanceof ObjectStamp)) { - return StampFactory.illegal(Kind.Illegal); - } - ObjectStamp other = (ObjectStamp) otherStamp; - if (!isLegal()) { - return this; - } else if (!other.isLegal()) { - return other; - } - - ResolvedJavaType joinType; - boolean joinAlwaysNull = alwaysNull || other.alwaysNull; - boolean joinNonNull = nonNull || other.nonNull; - boolean joinExactType = exactType || other.exactType; - if (Objects.equals(type, other.type)) { - joinType = type; - } else if (type == null && other.type == null) { - joinType = null; - } else if (type == null) { - joinType = other.type; - } else if (other.type == null) { - joinType = type; - } else { - // both types are != null and different - if (type.isAssignableFrom(other.type)) { - joinType = other.type; - if (exactType) { - joinAlwaysNull = true; - } - } else if (other.type.isAssignableFrom(type)) { - joinType = type; - if (other.exactType) { - joinAlwaysNull = true; - } - } else { - if (castToOther) { - joinType = other.type; - joinExactType = other.exactType; - } else { - joinType = null; - } - if (joinExactType || (!type.isInterface() && !other.type.isInterface())) { - joinAlwaysNull = true; - } - } - } - if (joinAlwaysNull) { - joinType = null; - joinExactType = false; - } - if (joinExactType && joinType == null) { - return StampFactory.illegal(Kind.Object); - } - if (joinAlwaysNull && joinNonNull) { - return StampFactory.illegal(Kind.Object); - } else if (joinExactType && !isConcreteType(joinType)) { - return StampFactory.illegal(Kind.Object); - } - if (Objects.equals(joinType, type) && joinExactType == exactType && joinNonNull == nonNull && joinAlwaysNull == alwaysNull) { - return this; - } else if (Objects.equals(joinType, other.type) && joinExactType == other.exactType && joinNonNull == other.nonNull && joinAlwaysNull == other.alwaysNull) { - return other; - } else { - return new ObjectStamp(joinType, joinExactType, joinNonNull, joinAlwaysNull); - } - } - - public static boolean isConcreteType(ResolvedJavaType type) { - return !(Modifier.isAbstract(type.getModifiers()) && !type.isArray()); - } - - private static ResolvedJavaType meetTypes(ResolvedJavaType a, ResolvedJavaType b) { - if (Objects.equals(a, b)) { - return a; - } else if (a == null || b == null) { - return null; - } else { - return a.findLeastCommonAncestor(b); - } - } - - @Override - public int hashCode() { - final int prime = 31; - int result = 1; - result = prime * result + (exactType ? 1231 : 1237); - result = prime * result + (nonNull ? 1231 : 1237); - result = prime * result + (alwaysNull ? 1231 : 1237); - result = prime * result + ((type == null) ? 0 : type.hashCode()); - return result; - } - - @Override - public boolean equals(Object obj) { - if (this == obj) { - return true; - } - if (obj == null || getClass() != obj.getClass()) { - return false; - } - ObjectStamp other = (ObjectStamp) obj; - if (exactType != other.exactType || nonNull != other.nonNull || alwaysNull != other.alwaysNull) { - return false; - } - if (type == null) { - if (other.type != null) { - return false; - } - } else if (!type.equals(other.type)) { - return false; - } - return true; - } - - public static boolean isObjectAlwaysNull(ValueNode node) { - return isObjectAlwaysNull(node.stamp()); - } - - public static boolean isObjectAlwaysNull(Stamp stamp) { - return (stamp instanceof ObjectStamp && ((ObjectStamp) stamp).isLegal() && ((ObjectStamp) stamp).alwaysNull()); - } - - public static boolean isObjectNonNull(ValueNode node) { - return isObjectNonNull(node.stamp()); - } - - public static boolean isObjectNonNull(Stamp stamp) { - return stamp instanceof ObjectStamp && ((ObjectStamp) stamp).isLegal() && ((ObjectStamp) stamp).nonNull(); - } - - public static ResolvedJavaType typeOrNull(ValueNode node) { - return typeOrNull(node.stamp()); - } - - public static ResolvedJavaType typeOrNull(Stamp stamp) { - if (stamp instanceof ObjectStamp) { - return ((ObjectStamp) stamp).type(); - } - return null; - } - - public static boolean isExactType(ValueNode node) { - return isExactType(node.stamp()); - } - - public static boolean isExactType(Stamp stamp) { - if (stamp instanceof ObjectStamp) { - return ((ObjectStamp) stamp).isExactType(); - } - return false; - } -} diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/type/PrimitiveStamp.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/type/PrimitiveStamp.java Fri Apr 25 16:21:07 2014 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,72 +0,0 @@ -/* - * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -package com.oracle.graal.nodes.type; - -import com.oracle.graal.nodes.*; - -/** - * Describes the possible values of a {@link ValueNode} that produces a primitive value as result. - */ -public abstract class PrimitiveStamp extends Stamp { - - private final int bits; - - protected PrimitiveStamp(int bits) { - this.bits = bits; - } - - /** - * The width in bits of the value described by this stamp. - */ - public int getBits() { - return bits; - } - - public static int getBits(Stamp stamp) { - if (stamp instanceof PrimitiveStamp) { - return ((PrimitiveStamp) stamp).getBits(); - } else { - return 0; - } - } - - @Override - public int hashCode() { - final int prime = 31; - int result = 1; - result = prime * result + bits; - return result; - } - - @Override - public boolean equals(Object obj) { - if (this == obj) { - return true; - } - if (obj instanceof PrimitiveStamp) { - PrimitiveStamp other = (PrimitiveStamp) obj; - return bits == other.bits; - } - return false; - } -} diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/type/Stamp.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/type/Stamp.java Fri Apr 25 16:21:07 2014 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,111 +0,0 @@ -/* - * Copyright (c) 2011, 2014, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -package com.oracle.graal.nodes.type; - -import com.oracle.graal.api.meta.*; -import com.oracle.graal.nodes.*; -import com.oracle.graal.nodes.spi.*; - -/** - * A stamp is the basis for a type system over the nodes in a graph. - */ -public abstract class Stamp { - - protected Stamp() { - } - - /** - * Returns the type of the stamp, guaranteed to be non-null. In some cases, this requires the - * lookup of class meta data, therefore the {@link MetaAccessProvider} is mandatory. - */ - public abstract ResolvedJavaType javaType(MetaAccessProvider metaAccess); - - public boolean alwaysDistinct(Stamp other) { - return !join(other).isLegal(); - } - - /** - * Gets a Java {@link Kind} that can be used to store a value of this stamp on the Java bytecode - * stack. Returns {@link Kind#Illegal} if a value of this stamp can not be stored on the - * bytecode stack. - */ - public abstract Kind getStackKind(); - - /** - * Gets a platform dependent {@link PlatformKind} that can be used to store a value of this - * stamp. - */ - public abstract PlatformKind getPlatformKind(LIRTypeTool tool); - - /** - * Returns the union of this stamp and the given stamp. Typically used to create stamps for - * {@link ValuePhiNode}s. - * - * @param other The stamp that will enlarge this stamp. - * @return The union of this stamp and the given stamp. - */ - public abstract Stamp meet(Stamp other); - - /** - * Returns the intersection of this stamp and the given stamp. - * - * @param other The stamp that will tighten this stamp. - * @return The intersection of this stamp and the given stamp. - */ - public abstract Stamp join(Stamp other); - - /** - * Returns a stamp of the same kind, but allowing the full value range of the kind. - * - * {@link #unrestricted()} is the neutral element of the {@link #join(Stamp)} operation. - */ - public abstract Stamp unrestricted(); - - /** - * Returns a stamp of the same kind, but with no allowed values. - * - * {@link #illegal()} is the neutral element of the {@link #meet(Stamp)} operation. - */ - public abstract Stamp illegal(); - - /** - * Test whether two stamps have the same base type. - */ - public abstract boolean isCompatible(Stamp other); - - /** - * Test whether this stamp has legal values. - */ - public abstract boolean isLegal(); - - /** - * If this stamp represents a single value, the methods returns this single value. It returns - * null otherwise. - * - * @return the constant corresponding to the single value of this stamp and null if this stamp - * can represent less or more than one value. - */ - public Constant asConstant() { - return null; - } -} diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/type/StampFactory.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/type/StampFactory.java Fri Apr 25 16:21:07 2014 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,254 +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.nodes.type; - -import com.oracle.graal.api.meta.*; -import com.oracle.graal.graph.*; - -public class StampFactory { - - // JaCoCo Exclude - - private static final Stamp[] stampCache = new Stamp[Kind.values().length]; - private static final Stamp[] illegalStampCache = new Stamp[Kind.values().length]; - private static final Stamp objectStamp = new ObjectStamp(null, false, false, false); - private static final Stamp objectNonNullStamp = new ObjectStamp(null, false, true, false); - private static final Stamp objectAlwaysNullStamp = new ObjectStamp(null, false, false, true); - private static final Stamp nodeIntrinsicStamp = new ObjectStamp(null, false, false, false); - private static final Stamp positiveInt = forInteger(Kind.Int, 0, Integer.MAX_VALUE, 0, Integer.MAX_VALUE); - - private static void setCache(Kind kind, Stamp stamp) { - stampCache[kind.ordinal()] = stamp; - } - - private static void setIntCache(Kind kind) { - int bits = kind.getStackKind().getBitCount(); - long mask; - if (kind.isUnsigned()) { - mask = IntegerStamp.defaultMask(kind.getBitCount()); - } else { - mask = IntegerStamp.defaultMask(bits); - } - setCache(kind, new IntegerStamp(bits, false, kind.getMinValue(), kind.getMaxValue(), 0, mask)); - } - - private static void setFloatCache(Kind kind) { - setCache(kind, new FloatStamp(kind.getBitCount())); - } - - static { - setIntCache(Kind.Boolean); - setIntCache(Kind.Byte); - setIntCache(Kind.Short); - setIntCache(Kind.Char); - setIntCache(Kind.Int); - setIntCache(Kind.Long); - - setFloatCache(Kind.Float); - setFloatCache(Kind.Double); - - setCache(Kind.Object, objectStamp); - setCache(Kind.Void, VoidStamp.getInstance()); - - for (Kind k : Kind.values()) { - if (stampCache[k.ordinal()] != null) { - illegalStampCache[k.ordinal()] = stampCache[k.ordinal()].illegal(); - } else { - illegalStampCache[k.ordinal()] = IllegalStamp.getInstance(); - } - } - } - - /** - * Return a stamp for a Java kind, as it would be represented on the bytecode stack. - */ - public static Stamp forKind(Kind kind) { - assert stampCache[kind.ordinal()] != null : "unexpected forKind(" + kind + ")"; - return stampCache[kind.ordinal()]; - } - - /** - * Return the stamp for the {@code void} type. This will return a singleton instance than can be - * compared using {@code ==}. - */ - public static Stamp forVoid() { - return VoidStamp.getInstance(); - } - - /** - * A stamp used only in the graph of intrinsics, e.g., snippets. It is then replaced by an - * actual stamp when the intrinsic is used, i.e., when the snippet template is instantiated. - */ - public static Stamp forNodeIntrinsic() { - return nodeIntrinsicStamp; - } - - public static Stamp intValue() { - return forKind(Kind.Int); - } - - public static Stamp positiveInt() { - return positiveInt; - } - - public static Stamp illegal() { - return illegal(Kind.Illegal); - } - - public static Stamp illegal(Kind kind) { - return illegalStampCache[kind.ordinal()]; - } - - public static IntegerStamp forInteger(Kind kind, long lowerBound, long upperBound, long downMask, long upMask) { - return new IntegerStamp(kind.getBitCount(), kind.isUnsigned(), lowerBound, upperBound, downMask, upMask); - } - - public static IntegerStamp forInteger(Kind kind, long lowerBound, long upperBound) { - return forInteger(kind.getBitCount(), kind.isUnsigned(), lowerBound, upperBound); - } - - public static IntegerStamp forInteger(int bits, boolean unsigned) { - return new IntegerStamp(bits, unsigned, IntegerStamp.defaultMinValue(bits, unsigned), IntegerStamp.defaultMaxValue(bits, unsigned), 0, IntegerStamp.defaultMask(bits)); - } - - public static IntegerStamp forInteger(int bits, boolean unsigned, long lowerBound, long upperBound) { - long defaultMask = IntegerStamp.defaultMask(bits); - if (lowerBound == upperBound) { - return new IntegerStamp(bits, unsigned, lowerBound, lowerBound, lowerBound & defaultMask, lowerBound & defaultMask); - } - final long downMask; - final long upMask; - if (lowerBound >= 0) { - int upperBoundLeadingZeros = Long.numberOfLeadingZeros(upperBound); - long differentBits = lowerBound ^ upperBound; - int sameBitCount = Long.numberOfLeadingZeros(differentBits << upperBoundLeadingZeros); - - upMask = upperBound | -1L >>> (upperBoundLeadingZeros + sameBitCount); - downMask = upperBound & ~(-1L >>> (upperBoundLeadingZeros + sameBitCount)); - } else { - if (upperBound >= 0) { - upMask = defaultMask; - downMask = 0; - } else { - int lowerBoundLeadingOnes = Long.numberOfLeadingZeros(~lowerBound); - long differentBits = lowerBound ^ upperBound; - int sameBitCount = Long.numberOfLeadingZeros(differentBits << lowerBoundLeadingOnes); - - upMask = lowerBound | -1L >>> (lowerBoundLeadingOnes + sameBitCount) | ~(-1L >>> lowerBoundLeadingOnes); - downMask = lowerBound & ~(-1L >>> (lowerBoundLeadingOnes + sameBitCount)) | ~(-1L >>> lowerBoundLeadingOnes); - } - } - return new IntegerStamp(bits, unsigned, lowerBound, upperBound, downMask & defaultMask, upMask & defaultMask); - } - - public static FloatStamp forFloat(Kind kind, double lowerBound, double upperBound, boolean nonNaN) { - assert kind.isNumericFloat(); - return new FloatStamp(kind.getBitCount(), lowerBound, upperBound, nonNaN); - } - - public static Stamp forConstant(Constant value) { - Kind kind = value.getKind(); - switch (kind) { - case Boolean: - case Byte: - case Char: - case Short: - case Int: - case Long: - long mask = value.asLong() & IntegerStamp.defaultMask(kind.getBitCount()); - return forInteger(kind.getStackKind(), value.asLong(), value.asLong(), mask, mask); - case Float: - return forFloat(kind, value.asFloat(), value.asFloat(), !Float.isNaN(value.asFloat())); - case Double: - return forFloat(kind, value.asDouble(), value.asDouble(), !Double.isNaN(value.asDouble())); - case Illegal: - return illegal(Kind.Illegal); - case Object: - if (value.isNull()) { - return alwaysNull(); - } else { - return objectNonNull(); - } - default: - throw new GraalInternalError("unexpected kind: %s", kind); - } - } - - public static Stamp forConstant(Constant value, MetaAccessProvider metaAccess) { - assert value.getKind() == Kind.Object; - if (value.getKind() == Kind.Object) { - ResolvedJavaType type = value.isNull() ? null : metaAccess.lookupJavaType(value); - return new ObjectStamp(type, value.isNonNull(), value.isNonNull(), value.isNull()); - } else { - throw new GraalInternalError(Kind.Object + " expected, actual kind: %s", value.getKind()); - } - } - - public static Stamp object() { - return objectStamp; - } - - public static Stamp objectNonNull() { - return objectNonNullStamp; - } - - public static Stamp alwaysNull() { - return objectAlwaysNullStamp; - } - - public static Stamp declared(ResolvedJavaType type) { - return declared(type, false); - } - - public static Stamp declaredNonNull(ResolvedJavaType type) { - return declared(type, true); - } - - public static Stamp declared(ResolvedJavaType type, boolean nonNull) { - return object(type, false, nonNull); - } - - public static Stamp object(ResolvedJavaType type, boolean exactType, boolean nonNull) { - assert type != null; - assert type.getKind() == Kind.Object; - ResolvedJavaType exact = type.asExactType(); - if (exact != null) { - assert !exactType || type.equals(exact); - return new ObjectStamp(exact, true, nonNull, false); - } else { - return new ObjectStamp(type, exactType, nonNull, false); - } - } - - public static Stamp exactNonNull(ResolvedJavaType type) { - if (ObjectStamp.isConcreteType(type)) { - return new ObjectStamp(type, true, true, false); - } else { - return illegal(Kind.Object); - } - } - - public static Stamp exact(ResolvedJavaType type) { - return new ObjectStamp(type, true, false, false); - } -} diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/type/StampProvider.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/type/StampProvider.java Fri Apr 25 16:21:07 2014 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,28 +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.nodes.type; - -public interface StampProvider { - - Stamp stamp(); -} diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/type/StampTool.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/type/StampTool.java Fri Apr 25 16:21:07 2014 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/type/StampTool.java Mon Apr 28 11:18:15 2014 +0200 @@ -25,6 +25,8 @@ import java.util.*; import com.oracle.graal.api.meta.*; +import com.oracle.graal.compiler.common.type.*; +import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.calc.*; /** @@ -36,9 +38,9 @@ if (stamp instanceof IntegerStamp) { IntegerStamp integerStamp = (IntegerStamp) stamp; int bits = integerStamp.getBits(); - if (integerStamp.lowerBound() != IntegerStamp.defaultMinValue(bits, false)) { + if (integerStamp.lowerBound() != IntegerStamp.defaultMinValue(bits)) { // TODO(ls) check if the mask calculation is correct... - return StampFactory.forInteger(bits, false, -integerStamp.upperBound(), -integerStamp.lowerBound()); + return StampFactory.forInteger(bits, -integerStamp.upperBound(), -integerStamp.lowerBound()); } } else if (stamp instanceof FloatStamp) { FloatStamp floatStamp = (FloatStamp) stamp; @@ -53,8 +55,7 @@ IntegerStamp integerStamp = (IntegerStamp) stamp; int bits = integerStamp.getBits(); long defaultMask = IntegerStamp.defaultMask(bits); - return new IntegerStamp(bits, integerStamp.isUnsigned(), ~integerStamp.upperBound(), ~integerStamp.lowerBound(), (~integerStamp.upMask()) & defaultMask, (~integerStamp.downMask()) & - defaultMask); + return new IntegerStamp(bits, ~integerStamp.upperBound(), ~integerStamp.lowerBound(), (~integerStamp.upMask()) & defaultMask, (~integerStamp.downMask()) & defaultMask); } return stamp.unrestricted(); } @@ -95,45 +96,36 @@ } public static Stamp div(IntegerStamp stamp1, IntegerStamp stamp2) { - assert stamp1.getBits() == stamp2.getBits() && stamp1.isUnsigned() == stamp2.isUnsigned(); + assert stamp1.getBits() == stamp2.getBits(); if (stamp2.isStrictlyPositive()) { long lowerBound = stamp1.lowerBound() / stamp2.lowerBound(); long upperBound = stamp1.upperBound() / stamp2.lowerBound(); - return StampFactory.forInteger(stamp1.getBits(), stamp1.isUnsigned(), lowerBound, upperBound); + return StampFactory.forInteger(stamp1.getBits(), lowerBound, upperBound); } return stamp1.unrestricted(); } - private static boolean addOverflowsPositively(long x, long y, int bits, boolean unsigned) { + private static boolean addOverflowsPositively(long x, long y, int bits) { long result = x + y; if (bits == 64) { - if (unsigned) { - return ((x | y) & ~result) < 0; - } else { - return (~x & ~y & result) < 0; - } + return (~x & ~y & result) < 0; } else { - return result > IntegerStamp.defaultMaxValue(bits, unsigned); + return result > IntegerStamp.defaultMaxValue(bits); } } - private static boolean addOverflowsNegatively(long x, long y, int bits, boolean unsigned) { - if (unsigned) { - return false; - } - + private static boolean addOverflowsNegatively(long x, long y, int bits) { long result = x + y; if (bits == 64) { return (x & y & ~result) < 0; } else { - return result < IntegerStamp.defaultMinValue(bits, unsigned); + return result < IntegerStamp.defaultMinValue(bits); } } public static IntegerStamp add(IntegerStamp stamp1, IntegerStamp stamp2) { int bits = stamp1.getBits(); - boolean unsigned = stamp1.isUnsigned(); - assert bits == stamp2.getBits() && unsigned == stamp2.isUnsigned(); + assert bits == stamp2.getBits(); if (stamp1.isUnrestricted()) { return stamp1; @@ -151,30 +143,23 @@ long lowerBound; long upperBound; - boolean lowerOverflowsPositively = addOverflowsPositively(stamp1.lowerBound(), stamp2.lowerBound(), bits, unsigned); - boolean upperOverflowsPositively = addOverflowsPositively(stamp1.upperBound(), stamp2.upperBound(), bits, unsigned); - boolean lowerOverflowsNegatively = addOverflowsNegatively(stamp1.lowerBound(), stamp2.lowerBound(), bits, unsigned); - boolean upperOverflowsNegatively = addOverflowsNegatively(stamp1.upperBound(), stamp2.upperBound(), bits, unsigned); + boolean lowerOverflowsPositively = addOverflowsPositively(stamp1.lowerBound(), stamp2.lowerBound(), bits); + boolean upperOverflowsPositively = addOverflowsPositively(stamp1.upperBound(), stamp2.upperBound(), bits); + boolean lowerOverflowsNegatively = addOverflowsNegatively(stamp1.lowerBound(), stamp2.lowerBound(), bits); + boolean upperOverflowsNegatively = addOverflowsNegatively(stamp1.upperBound(), stamp2.upperBound(), bits); if ((lowerOverflowsNegatively && !upperOverflowsNegatively) || (!lowerOverflowsPositively && upperOverflowsPositively)) { - lowerBound = IntegerStamp.defaultMinValue(bits, unsigned); - upperBound = IntegerStamp.defaultMaxValue(bits, unsigned); + lowerBound = IntegerStamp.defaultMinValue(bits); + upperBound = IntegerStamp.defaultMaxValue(bits); } else { - lowerBound = (stamp1.lowerBound() + stamp2.lowerBound()) & defaultMask; - upperBound = (stamp1.upperBound() + stamp2.upperBound()) & defaultMask; - if (!unsigned) { - lowerBound = SignExtendNode.signExtend(lowerBound, bits); - upperBound = SignExtendNode.signExtend(upperBound, bits); - } + lowerBound = SignExtendNode.signExtend((stamp1.lowerBound() + stamp2.lowerBound()) & defaultMask, bits); + upperBound = SignExtendNode.signExtend((stamp1.upperBound() + stamp2.upperBound()) & defaultMask, bits); } - IntegerStamp limit = StampFactory.forInteger(bits, unsigned, lowerBound, upperBound); + IntegerStamp limit = StampFactory.forInteger(bits, lowerBound, upperBound); newUpMask &= limit.upMask(); - upperBound &= newUpMask; - if (!unsigned) { - upperBound = SignExtendNode.signExtend(upperBound, bits); - } + upperBound = SignExtendNode.signExtend(upperBound & newUpMask, bits); newDownMask |= limit.downMask(); lowerBound |= newDownMask; - return new IntegerStamp(bits, unsigned, lowerBound, upperBound, newDownMask, newUpMask); + return new IntegerStamp(bits, lowerBound, upperBound, newDownMask, newUpMask); } public static Stamp sub(IntegerStamp stamp1, IntegerStamp stamp2) { @@ -195,11 +180,11 @@ upperBound = upMask; } else { lowerBound = downMask | (-1L << (bits - 1)); - upperBound = IntegerStamp.defaultMaxValue(bits, false) & upMask; + upperBound = IntegerStamp.defaultMaxValue(bits) & upMask; } lowerBound = IntegerConvertNode.convert(lowerBound, bits, false); upperBound = IntegerConvertNode.convert(upperBound, bits, false); - return new IntegerStamp(bits, false, lowerBound, upperBound, downMask, upMask); + return new IntegerStamp(bits, lowerBound, upperBound, downMask, upMask); } public static Stamp and(Stamp stamp1, Stamp stamp2) { @@ -265,7 +250,7 @@ lowerBound = value.lowerBound() >>> shiftCount; upperBound = value.upperBound() >>> shiftCount; } - return new IntegerStamp(bits, value.isUnsigned(), lowerBound, upperBound, downMask, upMask); + return new IntegerStamp(bits, lowerBound, upperBound, downMask, upMask); } } long mask = IntegerStamp.upMaskFor(bits, value.lowerBound(), value.upperBound()); @@ -312,17 +297,7 @@ long downMask = SignExtendNode.signExtend(inputStamp.downMask(), inputBits) & defaultMask; long upMask = SignExtendNode.signExtend(inputStamp.upMask(), inputBits) & defaultMask; - long lowerBound; - long upperBound; - if (inputStamp.isUnsigned()) { - lowerBound = SignExtendNode.signExtend(inputStamp.lowerBound(), inputBits) & defaultMask; - upperBound = SignExtendNode.signExtend(inputStamp.upperBound(), inputBits) & defaultMask; - } else { - lowerBound = inputStamp.lowerBound(); - upperBound = inputStamp.upperBound(); - } - - return new IntegerStamp(resultBits, inputStamp.isUnsigned(), lowerBound, upperBound, downMask, upMask); + return new IntegerStamp(resultBits, inputStamp.lowerBound(), inputStamp.upperBound(), downMask, upMask); } else { return input.illegal(); } @@ -346,7 +321,7 @@ long lowerBound = ZeroExtendNode.zeroExtend(inputStamp.lowerBound(), inputBits); long upperBound = ZeroExtendNode.zeroExtend(inputStamp.upperBound(), inputBits); - return new IntegerStamp(resultBits, inputStamp.isUnsigned(), lowerBound, upperBound, downMask, upMask); + return new IntegerStamp(resultBits, lowerBound, upperBound, downMask, upMask); } else { return input.illegal(); } @@ -355,7 +330,6 @@ public static Stamp narrowingConversion(Stamp input, int resultBits) { if (input instanceof IntegerStamp) { IntegerStamp inputStamp = (IntegerStamp) input; - boolean unsigned = inputStamp.isUnsigned(); int inputBits = inputStamp.getBits(); assert resultBits <= inputBits; if (resultBits == inputBits) { @@ -363,28 +337,24 @@ } final long upperBound; - if (inputStamp.lowerBound() < IntegerStamp.defaultMinValue(resultBits, unsigned)) { - upperBound = IntegerStamp.defaultMaxValue(resultBits, unsigned); + if (inputStamp.lowerBound() < IntegerStamp.defaultMinValue(resultBits)) { + upperBound = IntegerStamp.defaultMaxValue(resultBits); } else { - upperBound = saturate(inputStamp.upperBound(), resultBits, unsigned); + upperBound = saturate(inputStamp.upperBound(), resultBits); } final long lowerBound; - if (inputStamp.upperBound() > IntegerStamp.defaultMaxValue(resultBits, unsigned)) { - lowerBound = IntegerStamp.defaultMinValue(resultBits, unsigned); + if (inputStamp.upperBound() > IntegerStamp.defaultMaxValue(resultBits)) { + lowerBound = IntegerStamp.defaultMinValue(resultBits); } else { - lowerBound = saturate(inputStamp.lowerBound(), resultBits, unsigned); + lowerBound = saturate(inputStamp.lowerBound(), resultBits); } long defaultMask = IntegerStamp.defaultMask(resultBits); long newDownMask = inputStamp.downMask() & defaultMask; long newUpMask = inputStamp.upMask() & defaultMask; - long newLowerBound = (lowerBound | newDownMask) & newUpMask; - long newUpperBound = (upperBound | newDownMask) & newUpMask; - if (!unsigned) { - newLowerBound = SignExtendNode.signExtend(newLowerBound, resultBits); - newUpperBound = SignExtendNode.signExtend(newUpperBound, resultBits); - } - return new IntegerStamp(resultBits, unsigned, newLowerBound, newUpperBound, newDownMask, newUpMask); + long newLowerBound = SignExtendNode.signExtend((lowerBound | newDownMask) & newUpMask, resultBits); + long newUpperBound = SignExtendNode.signExtend((upperBound | newDownMask) & newUpMask, resultBits); + return new IntegerStamp(resultBits, newLowerBound, newUpperBound, newDownMask, newUpMask); } else { return input.illegal(); } @@ -409,7 +379,7 @@ long intMask = IntegerStamp.defaultMask(32); long newUpMask = signExtend(fromStamp.upMask() & defaultMask, toKind) & intMask; long newDownMask = signExtend(fromStamp.downMask() & defaultMask, toKind) & intMask; - return new IntegerStamp(toKind.getStackKind().getBitCount(), false, (int) ((lowerBound | newDownMask) & newUpMask), (int) ((upperBound | newDownMask) & newUpMask), newDownMask, newUpMask); + return new IntegerStamp(toKind.getStackKind().getBitCount(), (int) ((lowerBound | newDownMask) & newUpMask), (int) ((upperBound | newDownMask) & newUpMask), newDownMask, newUpMask); } private static long signExtend(long value, Kind valueKind) { @@ -420,13 +390,13 @@ } } - private static long saturate(long v, int bits, boolean unsigned) { + private static long saturate(long v, int bits) { if (bits < 64) { - long max = IntegerStamp.defaultMaxValue(bits, unsigned); + long max = IntegerStamp.defaultMaxValue(bits); if (v > max) { return max; } - long min = IntegerStamp.defaultMinValue(bits, unsigned); + long min = IntegerStamp.defaultMinValue(bits); if (v < min) { return min; } @@ -471,15 +441,121 @@ } // If the test succeeds then this proves that n is at greater than c so the bounds // are [c+1..-n.upperBound)]. - return StampFactory.forInteger(x.getBits(), false, x.lowerBound() + 1, y.upperBound()); + return StampFactory.forInteger(x.getBits(), x.lowerBound() + 1, y.upperBound()); } return null; } // n <| c, where c is a strictly positive constant if (y.lowerBound() == y.upperBound() && y.isStrictlyPositive()) { // The test proves that n is positive and less than c, [0..c-1] - return StampFactory.forInteger(y.getBits(), false, 0, y.lowerBound() - 1); + return StampFactory.forInteger(y.getBits(), 0, y.lowerBound() - 1); } return null; } + + /** + * Checks whether this {@link ValueNode} represents a {@linkplain Stamp#isLegal() legal} Object + * value which is known to be always null. + * + * @param node the node to check + * @return true if this node represents a legal object value which is known to be always null + */ + public static boolean isObjectAlwaysNull(ValueNode node) { + return isObjectAlwaysNull(node.stamp()); + } + + /** + * Checks whether this {@link Stamp} represents a {@linkplain Stamp#isLegal() legal} Object + * stamp whose values are known to be always null. + * + * @param stamp the stamp to check + * @return true if this stamp represents a legal object stamp whose values are known to be + * always null + */ + public static boolean isObjectAlwaysNull(Stamp stamp) { + if (stamp instanceof ObjectStamp && stamp.isLegal()) { + return ((ObjectStamp) stamp).alwaysNull(); + } + return false; + } + + /** + * Checks whether this {@link ValueNode} represents a {@linkplain Stamp#isLegal() legal} Object + * value which is known to never be null. + * + * @param node the node to check + * @return true if this node represents a legal object value which is known to never be null + */ + public static boolean isObjectNonNull(ValueNode node) { + return isObjectNonNull(node.stamp()); + } + + /** + * Checks whether this {@link Stamp} represents a {@linkplain Stamp#isLegal() legal} Object + * stamp whose values known to be always null. + * + * @param stamp the stamp to check + * @return true if this stamp represents a legal object stamp whose values are known to be + * always null + */ + public static boolean isObjectNonNull(Stamp stamp) { + if (stamp instanceof ObjectStamp && stamp.isLegal()) { + return ((ObjectStamp) stamp).nonNull(); + } + return false; + } + + /** + * Returns the {@linkplain ResolvedJavaType Java type} this {@linkplain ValueNode} has if it is + * a {@linkplain Stamp#isLegal() legal} Object value. + * + * @param node the node to check + * @return the Java type this value has if it is a legal Object type, null otherwise + */ + public static ResolvedJavaType typeOrNull(ValueNode node) { + return typeOrNull(node.stamp()); + } + + /** + * Returns the {@linkplain ResolvedJavaType Java type} this {@linkplain Stamp} has if it is a + * {@linkplain Stamp#isLegal() legal} Object stamp. + * + * @param stamp the stamp to check + * @return the Java type this stamp has if it is a legal Object stamp, null otherwise + */ + public static ResolvedJavaType typeOrNull(Stamp stamp) { + if (stamp instanceof ObjectStamp && stamp.isLegal()) { + return ((ObjectStamp) stamp).type(); + } + return null; + } + + /** + * Checks whether this {@link ValueNode} represents a {@linkplain Stamp#isLegal() legal} Object + * value whose Java type is known exactly. If this method returns true then the + * {@linkplain ResolvedJavaType Java type} returned by {@link #typeOrNull(ValueNode)} is the + * concrete dynamic/runtime Java type of this value. + * + * @param node the node to check + * @return true if this node represents a legal object value whose Java type is known exactly + */ + public static boolean isExactType(ValueNode node) { + return isExactType(node.stamp()); + } + + /** + * Checks whether this {@link Stamp} represents a {@linkplain Stamp#isLegal() legal} Object + * stamp whose {@linkplain ResolvedJavaType Java type} is known exactly. If this method returns + * true then the Java type returned by {@link #typeOrNull(Stamp)} is the only concrete + * dynamic/runtime Java type possible for values of this stamp. + * + * @param stamp the stamp to check + * @return true if this node represents a legal object stamp whose Java type is known exactly + */ + public static boolean isExactType(Stamp stamp) { + if (stamp instanceof ObjectStamp && stamp.isLegal()) { + return ((ObjectStamp) stamp).isExactType(); + } + return false; + } } diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/type/VoidStamp.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/type/VoidStamp.java Fri Apr 25 16:21:07 2014 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,110 +0,0 @@ -/* - * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -package com.oracle.graal.nodes.type; - -import com.oracle.graal.api.meta.*; -import com.oracle.graal.graph.*; -import com.oracle.graal.nodes.spi.*; - -/** - * Singleton stamp representing the value of type {@code void}. - */ -public final class VoidStamp extends Stamp { - - private VoidStamp() { - } - - @Override - public Stamp unrestricted() { - return this; - } - - @Override - public Kind getStackKind() { - return Kind.Void; - } - - @Override - public PlatformKind getPlatformKind(LIRTypeTool tool) { - throw GraalInternalError.shouldNotReachHere("void stamp has no value"); - } - - @Override - public ResolvedJavaType javaType(MetaAccessProvider metaAccess) { - return metaAccess.lookupJavaType(Void.TYPE); - } - - @Override - public String toString() { - return "void"; - } - - @Override - public boolean alwaysDistinct(Stamp other) { - return this != other; - } - - @Override - public Stamp meet(Stamp other) { - if (other instanceof IllegalStamp) { - return other.join(this); - } - if (this == other) { - return this; - } - return StampFactory.illegal(Kind.Illegal); - } - - @Override - public Stamp join(Stamp other) { - if (other instanceof IllegalStamp) { - return other.join(this); - } - if (this == other) { - return this; - } - return StampFactory.illegal(Kind.Illegal); - } - - @Override - public boolean isCompatible(Stamp stamp) { - return this == stamp; - } - - @Override - public Stamp illegal() { - // there is no illegal void stamp - return this; - } - - @Override - public boolean isLegal() { - return true; - } - - private static VoidStamp instance = new VoidStamp(); - - static VoidStamp getInstance() { - return instance; - } -} diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/util/ComputeImmediateDominator.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/util/ComputeImmediateDominator.java Fri Apr 25 16:21:07 2014 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,262 +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.nodes.util; - -import java.util.*; - -import com.oracle.graal.graph.*; -import com.oracle.graal.nodes.*; - -public final class ComputeImmediateDominator { - - private final MergeNode dominated; - private final Queue toExplore; - private final Queue speculativeExplore; - private final NodeMap infoMap; - private final DominatorInfo fullInfo; - private FixedNode dominator; - private int nextBit = 1; - - public ComputeImmediateDominator(MergeNode dominated) { - this.dominated = dominated; - this.toExplore = new LinkedList<>(); - this.speculativeExplore = new LinkedList<>(); - this.infoMap = dominated.graph().createNodeMap(); - fullInfo = new DominatorInfo(dominated, true); - - this.processMerge(dominated, fullInfo); - if (toExplore.size() == 1) { - dominator = toExplore.remove(); - } - } - - public FixedNode compute() { - try { - while (dominator == null && (!toExplore.isEmpty() || !speculativeExplore.isEmpty())) { - while (!toExplore.isEmpty()) { - exploreUp(toExplore.remove()); - if (dominator != null) { - return dominator; - } - } - exploreUp(speculativeExplore.remove()); - } - return dominator; - } catch (Throwable t) { - throw new GraalInternalError(t).addContext("Could not find a dominator").addContext(dominated); - } - } - - private void exploreUp(FixedNode from) { - FixedNode p = from; - DominatorInfo info = infoMap.get(from); - if (info.isExplored()) { - return; - } - // TTY.println("exploreUp(" + from + ") with " + info); - info.setExplored(); - while (p != null) { - if (p instanceof MergeNode) { - processMerge((MergeNode) p, info); - p = null; - } else if (p instanceof ControlSplitNode) { - processControlSplit((ControlSplitNode) p, info); - p = null; - } else { - p = (FixedNode) p.predecessor(); - } - } - } - - private void processControlSplit(ControlSplitNode cs, DominatorInfo info) { - // TTY.println("processControlSplit(" + cs + ", " + info + ")"); - DominatorInfo csInfo = infoMap.get(cs); - if (csInfo == null) { - csInfo = new DominatorInfo(cs, false); - infoMap.set(cs, csInfo); - } - csInfo.add(info); - FixedNode next = (FixedNode) cs.predecessor(); - if (checkControlSplitInfo(csInfo)) { - return; - } - if (csInfo.isExplored()) { - // TTY.println(" Already explored, propagate update"); - propagateUpdate(csInfo); - } else { - if (csInfo.parentCount() == cs.successors().count()) { // all paths leading to this CS - // have been explored - // TTY.println(" All parents explored, Enqueue"); - toExplore.add(next); - speculativeExplore.remove(next); - } else { - // TTY.println(" Not all parents explored : Enqueue speculative"); - speculativeExplore.add(next); - } - } - infoMap.set(next, csInfo); - } - - private boolean propagateUpdate(DominatorInfo di) { - // TTY.println(" propagateUpdate(" + di + ")"); - for (DominatorInfo child : di.children()) { - // TTY.println(" add to child " + child); - if (child.add(di, false)) { - if (child.equals(fullInfo)) { - // TTY.println(" Found DOM!"); - dominator = child.node(); - return true; - } - if (propagateUpdate(child)) { - return true; - } - } - } - return false; - } - - private boolean checkControlSplitInfo(DominatorInfo di) { - // TTY.println(" checkControlSplitInfo(" + di + ")"); - if (di.equals(fullInfo)) { - dominator = di.node(); - // TTY.println(" Found DOM!"); - return true; - } - return false; - } - - private void processMerge(MergeNode merge, DominatorInfo info) { - // TTY.println("processMerge(" + merge + ", " + info + ")"); - for (AbstractEndNode end : merge.cfgPredecessors()) { - toExplore.add(end); - infoMap.set(end, info.createChild(end)); - // TTY.println(" Enqueue end : " + end + " with " + infoMap.get(end)); - } - } - - private class DominatorInfo { - - private final FixedNode node; - private final BitSet bits; - private final BitSet ownBits; - private final Collection children; - private final Collection parents; - private boolean explored; - - public DominatorInfo(FixedNode node, boolean full) { - this.node = node; - this.bits = new BitSet(); - this.ownBits = new BitSet(); - this.children = new ArrayList<>(2); - this.parents = new ArrayList<>(2); - if (full) { - addOwnBits(0); - } - } - - public boolean isExplored() { - return explored; - } - - public void setExplored() { - explored = true; - } - - public DominatorInfo createChild(FixedNode childNode) { - DominatorInfo di = new DominatorInfo(childNode, false); - di.bits.or(bits); - di.ownBits.or(ownBits); - if (!children.isEmpty() || di.ownBits.isEmpty()) { - int newBit = nextBit++; - di.bits.xor(ownBits); - di.bits.set(newBit); - di.ownBits.clear(); - di.ownBits.set(newBit); - addOwnBits(newBit); - } - children.add(di); - di.parents.add(this); - return di; - } - - private void addOwnBits(int newBit) { - if (!bits.get(newBit)) { - ownBits.set(newBit); - bits.set(newBit); - for (DominatorInfo parent : parents) { - parent.addOwnBits(newBit); - } - } - } - - public boolean add(DominatorInfo i) { - return add(i, true); - } - - public boolean add(DominatorInfo i, boolean addParent) { - boolean ret = true; - if (addParent) { - parents.add(i); - i.children.add(this); - bits.or(i.bits); - } else { - BitSet newBits = (BitSet) i.bits.clone(); - newBits.andNot(bits); - newBits.andNot(i.ownBits); - ret = !newBits.isEmpty(); - bits.or(newBits); - } - return ret; - } - - public int parentCount() { - return parents.size(); - } - - public FixedNode node() { - return node; - } - - public Collection children() { - return children; - } - - @Override - public boolean equals(Object obj) { - if (!(obj instanceof DominatorInfo)) { - return false; - } - return ((DominatorInfo) obj).bits.equals(bits); - } - - @Override - public String toString() { - return bits + " (o" + ownBits + ") " + node; - } - - @Override - public int hashCode() { - return bits.hashCode(); - } - } -} diff -r 3dde8d8c95b8 -r 40d0022115ee 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 Fri Apr 25 16:21:07 2014 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/util/GraphUtil.java Mon Apr 28 11:18:15 2014 +0200 @@ -38,7 +38,6 @@ @Override public final boolean apply(Node n) { - // isA(FloatingNode.class).or(VirtualState.class).or(CallTargetNode.class) return n instanceof FloatingNode || n instanceof VirtualState || n instanceof CallTargetNode; } }; @@ -138,6 +137,11 @@ } public static void removeFixedWithUnusedInputs(FixedWithNextNode fixed) { + if (fixed instanceof StateSplit) { + FrameState stateAfter = ((StateSplit) fixed).stateAfter(); + ((StateSplit) fixed).setStateAfter(null); + killWithUnusedFloatingInputs(stateAfter); + } FixedNode next = fixed.next(); fixed.setNext(null); fixed.replaceAtPredecessor(next); @@ -164,7 +168,7 @@ } public static void checkRedundantProxy(ProxyNode vpn) { - AbstractBeginNode proxyPoint = vpn.proxyPoint(); + BeginNode proxyPoint = vpn.proxyPoint(); if (proxyPoint instanceof LoopExitNode) { LoopExitNode exit = (LoopExitNode) proxyPoint; LoopBeginNode loopBegin = exit.loopBegin(); @@ -327,6 +331,14 @@ return v; } + public static boolean tryKillUnused(Node node) { + if (node.isAlive() && isFloatingNode().apply(node) && node.recordsUsages() && node.usages().isEmpty()) { + killWithUnusedFloatingInputs(node); + return true; + } + return false; + } + /** * Exhaustive search for {@link GraphUtil#originalValue(ValueNode)} when a simple search fails. * This can happen in the presence of complicated phi/proxy/phi constructs. diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/util/NodeIterators.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/util/NodeIterators.java Fri Apr 25 16:21:07 2014 +0200 +++ /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.nodes.util; - -import java.util.*; - -import com.oracle.graal.graph.iterators.*; -import com.oracle.graal.nodes.*; - -public class NodeIterators { - - public static NodeIterable dominators(final FixedNode n) { - return new AbstractNodeIterable() { - - @Override - public Iterator iterator() { - return new NodeIterator() { - - FixedNode p = n; - - @Override - protected void forward() { - if (current == null) { - if (p instanceof MergeNode) { - current = new ComputeImmediateDominator((MergeNode) p).compute(); - } else { - current = (FixedNode) p.predecessor(); - } - p = current; - } - } - }; - } - }; - } -} diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/util/TreeIterators.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/util/TreeIterators.java Fri Apr 25 16:21:07 2014 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,68 +0,0 @@ -/* - * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -package com.oracle.graal.nodes.util; - -import java.util.*; - -public class TreeIterators { - - public abstract static class PrefixTreeIterator implements Iterator { - - private Deque stack = new LinkedList<>(); - - public PrefixTreeIterator(T root) { - stack.push(root); - } - - public PrefixTreeIterator(Iterable roots) { - for (T root : roots) { - stack.addLast(root); - } - } - - @Override - public boolean hasNext() { - return !stack.isEmpty(); - } - - @Override - public T next() { - T top = stack.pop(); - LinkedList list = new LinkedList<>(); - for (T child : children(top)) { - list.addFirst(child); - } - for (T child : list) { - stack.push(child); - } - return top; - } - - @Override - public void remove() { - throw new UnsupportedOperationException(); - } - - protected abstract Iterable children(T node); - } -} diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/virtual/AllocatedObjectNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/virtual/AllocatedObjectNode.java Fri Apr 25 16:21:07 2014 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/virtual/AllocatedObjectNode.java Mon Apr 28 11:18:15 2014 +0200 @@ -22,11 +22,11 @@ */ package com.oracle.graal.nodes.virtual; +import com.oracle.graal.compiler.common.type.*; import com.oracle.graal.graph.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.calc.*; import com.oracle.graal.nodes.spi.*; -import com.oracle.graal.nodes.type.*; /** * Selects one object from a {@link CommitAllocationNode}. The object is identified by its diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/virtual/CommitAllocationNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/virtual/CommitAllocationNode.java Fri Apr 25 16:21:07 2014 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/virtual/CommitAllocationNode.java Mon Apr 28 11:18:15 2014 +0200 @@ -25,12 +25,12 @@ import java.util.*; import com.oracle.graal.api.meta.*; +import com.oracle.graal.compiler.common.type.*; import com.oracle.graal.graph.*; import com.oracle.graal.graph.spi.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.java.*; import com.oracle.graal.nodes.spi.*; -import com.oracle.graal.nodes.type.*; @NodeInfo(nameTemplate = "Alloc {i#virtualObjects}", allowedUsageTypes = {InputType.Extension}) public final class CommitAllocationNode extends FixedWithNextNode implements VirtualizableAllocation, Lowerable, Simplifiable { diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/virtual/VirtualObjectNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/virtual/VirtualObjectNode.java Fri Apr 25 16:21:07 2014 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/virtual/VirtualObjectNode.java Mon Apr 28 11:18:15 2014 +0200 @@ -23,10 +23,10 @@ package com.oracle.graal.nodes.virtual; import com.oracle.graal.api.meta.*; +import com.oracle.graal.compiler.common.type.*; import com.oracle.graal.graph.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.spi.*; -import com.oracle.graal.nodes.type.*; public abstract class VirtualObjectNode extends ValueNode implements LIRLowerable, IterableNodeType { diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.options/src/com/oracle/graal/options/OptionProcessor.java --- a/graal/com.oracle.graal.options/src/com/oracle/graal/options/OptionProcessor.java Fri Apr 25 16:21:07 2014 +0200 +++ b/graal/com.oracle.graal.options/src/com/oracle/graal/options/OptionProcessor.java Mon Apr 28 11:18:15 2014 +0200 @@ -40,8 +40,10 @@ * *

  * ServiceLoader<Options> sl = ServiceLoader.loadInstalled(Options.class);
- * for (OptionDescriptor desc : sl) {
- *     // use desc
+ * for (Options opts : sl) {
+ *     for (OptionDescriptor desc : sl) {
+ *         // use desc
+ *     }
  * }
  * 
*/ diff -r 3dde8d8c95b8 -r 40d0022115ee 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 Fri Apr 25 16:21:07 2014 +0200 +++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/CanonicalizerPhase.java Mon Apr 28 11:18:15 2014 +0200 @@ -178,7 +178,7 @@ } StructuredGraph graph = (StructuredGraph) node.graph(); Mark mark = graph.getMark(); - if (!tryKillUnused(node)) { + if (!GraphUtil.tryKillUnused(node)) { if (!tryCanonicalize(node, nodeClass)) { if (node instanceof ValueNode) { ValueNode valueNode = (ValueNode) node; @@ -200,14 +200,6 @@ } } - private static boolean tryKillUnused(Node node) { - if (node.isAlive() && GraphUtil.isFloatingNode().apply(node) && node.recordsUsages() && node.usages().isEmpty()) { - GraphUtil.killWithUnusedFloatingInputs(node); - return true; - } - return false; - } - public static boolean tryGlobalValueNumbering(Node node, NodeClass nodeClass) { if (nodeClass.valueNumberable() && !nodeClass.isLeafNode()) { Node newNode = node.graph().findDuplicate(node); @@ -383,7 +375,7 @@ @Override public void removeIfUnused(Node node) { - tryKillUnused(node); + GraphUtil.tryKillUnused(node); } @Override diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/ConditionalEliminationPhase.java --- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/ConditionalEliminationPhase.java Fri Apr 25 16:21:07 2014 +0200 +++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/ConditionalEliminationPhase.java Mon Apr 28 11:18:15 2014 +0200 @@ -22,10 +22,10 @@ */ package com.oracle.graal.phases.common; -import java.lang.reflect.*; import java.util.*; import com.oracle.graal.api.meta.*; +import com.oracle.graal.compiler.common.type.*; import com.oracle.graal.debug.*; import com.oracle.graal.debug.Debug.Scope; import com.oracle.graal.graph.*; @@ -151,7 +151,7 @@ break; } } - if (type != null && type != ObjectStamp.typeOrNull(node)) { + if (type != null && type != StampTool.typeOrNull(node)) { newKnownTypes.put(node, type); } } @@ -234,15 +234,15 @@ public ResolvedJavaType getNodeType(ValueNode node) { ResolvedJavaType result = knownTypes.get(GraphUtil.unproxify(node)); - return result == null ? ObjectStamp.typeOrNull(node) : result; + return result == null ? StampTool.typeOrNull(node) : result; } public boolean isNull(ValueNode value) { - return ObjectStamp.isObjectAlwaysNull(value) || knownNull.contains(GraphUtil.unproxify(value)); + return StampTool.isObjectAlwaysNull(value) || knownNull.contains(GraphUtil.unproxify(value)); } public boolean isNonNull(ValueNode value) { - return ObjectStamp.isObjectNonNull(value) || knownNonNull.contains(GraphUtil.unproxify(value)); + return StampTool.isObjectNonNull(value) || knownNonNull.contains(GraphUtil.unproxify(value)); } @Override @@ -407,7 +407,7 @@ } } - private void registerControlSplitInfo(Node pred, AbstractBeginNode begin) { + private void registerControlSplitInfo(Node pred, BeginNode begin) { assert pred != null && begin != null; if (begin instanceof LoopExitNode) { state.clear(); @@ -656,8 +656,8 @@ @Override protected void node(FixedNode node) { - if (node instanceof AbstractBeginNode) { - AbstractBeginNode begin = (AbstractBeginNode) node; + if (node instanceof BeginNode) { + BeginNode begin = (BeginNode) node; Node pred = node.predecessor(); if (pred != null) { @@ -742,7 +742,7 @@ LogicNode replacement = null; ValueNode replacementAnchor = null; - AbstractBeginNode survivingSuccessor = null; + BeginNode survivingSuccessor = null; if (state.trueConditions.containsKey(compare)) { replacement = trueConstant; replacementAnchor = state.trueConditions.get(compare); @@ -764,7 +764,7 @@ } if (replacement != null) { - if (!(replacementAnchor instanceof AbstractBeginNode)) { + if (!(replacementAnchor instanceof BeginNode)) { ValueAnchorNode anchor = graph.add(new ValueAnchorNode(replacementAnchor)); graph.addBeforeFixed(ifNode, anchor); } @@ -811,10 +811,10 @@ ValueNode receiver = callTarget.receiver(); if (receiver != null && (callTarget.invokeKind() == InvokeKind.Interface || callTarget.invokeKind() == InvokeKind.Virtual)) { ResolvedJavaType type = state.getNodeType(receiver); - if (!Objects.equals(type, ObjectStamp.typeOrNull(receiver))) { + if (!Objects.equals(type, StampTool.typeOrNull(receiver))) { ResolvedJavaMethod method = type.resolveMethod(callTarget.targetMethod()); if (method != null) { - if (Modifier.isFinal(method.getModifiers()) || Modifier.isFinal(type.getModifiers())) { + if (method.canBeStaticallyBound() || type.isFinal()) { callTarget.setInvokeKind(InvokeKind.Special); callTarget.setTargetMethod(method); } diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/ConvertDeoptimizeToGuardPhase.java --- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/ConvertDeoptimizeToGuardPhase.java Fri Apr 25 16:21:07 2014 +0200 +++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/ConvertDeoptimizeToGuardPhase.java Mon Apr 28 11:18:15 2014 +0200 @@ -47,11 +47,11 @@ */ public class ConvertDeoptimizeToGuardPhase extends Phase { - private static AbstractBeginNode findBeginNode(FixedNode startNode) { + private static BeginNode findBeginNode(FixedNode startNode) { Node n = startNode; while (true) { - if (n instanceof AbstractBeginNode) { - return (AbstractBeginNode) n; + if (n instanceof BeginNode) { + return (BeginNode) n; } else { n = n.predecessor(); } @@ -71,7 +71,7 @@ for (FixedGuardNode fixedGuard : graph.getNodes(FixedGuardNode.class)) { - AbstractBeginNode pred = BeginNode.prevBegin(fixedGuard); + BeginNode pred = BeginNode.prevBegin(fixedGuard); if (pred instanceof MergeNode) { MergeNode merge = (MergeNode) pred; if (fixedGuard.condition() instanceof CompareNode) { @@ -109,17 +109,17 @@ new DeadCodeEliminationPhase().apply(graph); } - private void visitDeoptBegin(AbstractBeginNode deoptBegin, DeoptimizationAction deoptAction, DeoptimizationReason deoptReason, StructuredGraph graph) { + private void visitDeoptBegin(BeginNode deoptBegin, DeoptimizationAction deoptAction, DeoptimizationReason deoptReason, StructuredGraph graph) { if (deoptBegin instanceof MergeNode) { MergeNode mergeNode = (MergeNode) deoptBegin; Debug.log("Visiting %s", mergeNode); - List begins = new ArrayList<>(); + List begins = new ArrayList<>(); for (AbstractEndNode end : mergeNode.forwardEnds()) { - AbstractBeginNode newBeginNode = findBeginNode(end); + BeginNode newBeginNode = findBeginNode(end); assert !begins.contains(newBeginNode); begins.add(newBeginNode); } - for (AbstractBeginNode begin : begins) { + for (BeginNode begin : begins) { assert !begin.isDeleted(); visitDeoptBegin(begin, deoptAction, deoptReason, graph); } @@ -127,11 +127,11 @@ return; } else if (deoptBegin.predecessor() instanceof IfNode) { IfNode ifNode = (IfNode) deoptBegin.predecessor(); - AbstractBeginNode otherBegin = ifNode.trueSuccessor(); + BeginNode otherBegin = ifNode.trueSuccessor(); LogicNode conditionNode = ifNode.condition(); FixedGuardNode guard = graph.add(new FixedGuardNode(conditionNode, deoptReason, deoptAction, deoptBegin == ifNode.trueSuccessor())); FixedWithNextNode pred = (FixedWithNextNode) ifNode.predecessor(); - AbstractBeginNode survivingSuccessor; + BeginNode survivingSuccessor; if (deoptBegin == ifNode.trueSuccessor()) { survivingSuccessor = ifNode.falseSuccessor(); } else { diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/DeoptimizationGroupingPhase.java --- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/DeoptimizationGroupingPhase.java Fri Apr 25 16:21:07 2014 +0200 +++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/DeoptimizationGroupingPhase.java Mon Apr 28 11:18:15 2014 +0200 @@ -25,9 +25,10 @@ import java.util.*; import com.oracle.graal.api.meta.*; +import com.oracle.graal.compiler.common.cfg.*; +import com.oracle.graal.compiler.common.type.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.cfg.*; -import com.oracle.graal.nodes.type.*; import com.oracle.graal.phases.*; import com.oracle.graal.phases.tiers.*; @@ -92,9 +93,9 @@ private static void exitLoops(AbstractDeoptimizeNode deopt, EndNode end, ControlFlowGraph cfg) { Block block = cfg.blockFor(deopt); - Loop loop = block.getLoop(); + Loop loop = block.getLoop(); while (loop != null) { - end.graph().addBeforeFixed(end, end.graph().add(new LoopExitNode(loop.loopBegin()))); + end.graph().addBeforeFixed(end, end.graph().add(new LoopExitNode((LoopBeginNode) loop.header.getBeginNode()))); loop = loop.parent; } } diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/ExpandLogicPhase.java --- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/ExpandLogicPhase.java Fri Apr 25 16:21:07 2014 +0200 +++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/ExpandLogicPhase.java Mon Apr 28 11:18:15 2014 +0200 @@ -22,6 +22,7 @@ */ package com.oracle.graal.phases.common; +import com.oracle.graal.compiler.common.*; import com.oracle.graal.graph.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.calc.*; @@ -54,8 +55,8 @@ } private static void processIf(LogicNode x, boolean xNegated, LogicNode y, boolean yNegated, IfNode ifNode, double shortCircuitProbability) { - AbstractBeginNode trueTarget = ifNode.trueSuccessor(); - AbstractBeginNode falseTarget = ifNode.falseSuccessor(); + BeginNode trueTarget = ifNode.trueSuccessor(); + BeginNode falseTarget = ifNode.falseSuccessor(); double firstIfProbability = shortCircuitProbability; /* * P(Y | not(X)) = P(Y inter not(X)) / P(not(X)) = (P(X union Y) - P(X)) / (1 - P(X)) @@ -77,9 +78,9 @@ EndNode secondTrueEnd = graph.add(new EndNode()); trueTargetMerge.addForwardEnd(firstTrueEnd); trueTargetMerge.addForwardEnd(secondTrueEnd); - AbstractBeginNode firstTrueTarget = AbstractBeginNode.begin(firstTrueEnd); - AbstractBeginNode secondTrueTarget = AbstractBeginNode.begin(secondTrueEnd); - AbstractBeginNode secondIf = AbstractBeginNode.begin(graph.add(new IfNode(y, yNegated ? falseTarget : secondTrueTarget, yNegated ? secondTrueTarget : falseTarget, secondIfProbability))); + BeginNode firstTrueTarget = BeginNode.begin(firstTrueEnd); + BeginNode secondTrueTarget = BeginNode.begin(secondTrueEnd); + BeginNode secondIf = BeginNode.begin(graph.add(new IfNode(y, yNegated ? falseTarget : secondTrueTarget, yNegated ? secondTrueTarget : falseTarget, secondIfProbability))); IfNode firstIf = graph.add(new IfNode(x, xNegated ? secondIf : firstTrueTarget, xNegated ? firstTrueTarget : secondIf, firstIfProbability)); ifNode.replaceAtPredecessor(firstIf); ifNode.safeDelete(); diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/FloatingReadPhase.java --- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/FloatingReadPhase.java Fri Apr 25 16:21:07 2014 +0200 +++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/FloatingReadPhase.java Mon Apr 28 11:18:15 2014 +0200 @@ -191,7 +191,7 @@ } @Override - protected Set afterSplit(AbstractBeginNode node, Set oldState) { + protected Set afterSplit(BeginNode node, Set oldState) { return new HashSet<>(oldState); } @@ -292,7 +292,7 @@ } @Override - protected MemoryMapImpl afterSplit(AbstractBeginNode node, MemoryMapImpl oldState) { + protected MemoryMapImpl afterSplit(BeginNode node, MemoryMapImpl oldState) { MemoryMapImpl result = new MemoryMapImpl(oldState); if (node.predecessor() instanceof InvokeWithExceptionNode) { /* diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/FrameStateAssignmentPhase.java --- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/FrameStateAssignmentPhase.java Fri Apr 25 16:21:07 2014 +0200 +++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/FrameStateAssignmentPhase.java Mon Apr 28 11:18:15 2014 +0200 @@ -24,6 +24,7 @@ import java.util.*; +import com.oracle.graal.compiler.common.*; import com.oracle.graal.graph.*; import com.oracle.graal.graph.iterators.*; import com.oracle.graal.nodes.*; @@ -92,7 +93,7 @@ } @Override - protected FrameState afterSplit(AbstractBeginNode node, FrameState oldState) { + protected FrameState afterSplit(BeginNode node, FrameState oldState) { return oldState; } diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/GuardLoweringPhase.java --- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/GuardLoweringPhase.java Fri Apr 25 16:21:07 2014 +0200 +++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/GuardLoweringPhase.java Mon Apr 28 11:18:15 2014 +0200 @@ -22,12 +22,13 @@ */ package com.oracle.graal.phases.common; -import static com.oracle.graal.phases.GraalOptions.*; +import static com.oracle.graal.compiler.common.GraalOptions.*; import java.util.*; import java.util.Map.Entry; import com.oracle.graal.api.meta.*; +import com.oracle.graal.compiler.common.cfg.*; import com.oracle.graal.debug.*; import com.oracle.graal.graph.*; import com.oracle.graal.nodes.*; @@ -154,12 +155,12 @@ private void lowerToIf(GuardNode guard) { StructuredGraph graph = guard.graph(); - AbstractBeginNode fastPath = graph.add(new BeginNode()); + BeginNode fastPath = graph.add(new BeginNode()); @SuppressWarnings("deprecation") DeoptimizeNode deopt = graph.add(new DeoptimizeNode(guard.action(), guard.reason(), useGuardIdAsDebugId ? guard.getId() : 0, guard.getSpeculation())); - AbstractBeginNode deoptBranch = AbstractBeginNode.begin(deopt); - AbstractBeginNode trueSuccessor; - AbstractBeginNode falseSuccessor; + BeginNode deoptBranch = BeginNode.begin(deopt); + BeginNode trueSuccessor; + BeginNode falseSuccessor; insertLoopExits(deopt); if (guard.negated()) { trueSuccessor = deoptBranch; @@ -174,10 +175,10 @@ } private void insertLoopExits(DeoptimizeNode deopt) { - Loop loop = block.getLoop(); + Loop loop = block.getLoop(); StructuredGraph graph = deopt.graph(); while (loop != null) { - LoopExitNode exit = graph.add(new LoopExitNode(loop.loopBegin())); + LoopExitNode exit = graph.add(new LoopExitNode((LoopBeginNode) loop.header.getBeginNode())); graph.addBeforeFixed(deopt, exit); loop = loop.parent; } diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/IncrementalCanonicalizerPhase.java --- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/IncrementalCanonicalizerPhase.java Fri Apr 25 16:21:07 2014 +0200 +++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/IncrementalCanonicalizerPhase.java Mon Apr 28 11:18:15 2014 +0200 @@ -40,6 +40,11 @@ this.canonicalizer = canonicalizer; } + public IncrementalCanonicalizerPhase(CanonicalizerPhase canonicalizer, BasePhase phase) { + this.canonicalizer = canonicalizer; + appendPhase(phase); + } + @Override protected void run(StructuredGraph graph, C context) { Mark newNodesMark = graph.getMark(); diff -r 3dde8d8c95b8 -r 40d0022115ee 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 Fri Apr 25 16:21:07 2014 +0200 +++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/InliningPhase.java Mon Apr 28 11:18:15 2014 +0200 @@ -22,13 +22,15 @@ */ package com.oracle.graal.phases.common; -import static com.oracle.graal.phases.GraalOptions.*; +import static com.oracle.graal.compiler.common.GraalOptions.*; import static com.oracle.graal.phases.common.InliningPhase.Options.*; import java.util.*; import com.oracle.graal.api.code.*; import com.oracle.graal.api.meta.*; +import com.oracle.graal.compiler.common.*; +import com.oracle.graal.compiler.common.type.*; import com.oracle.graal.debug.*; import com.oracle.graal.debug.Debug.Scope; import com.oracle.graal.graph.*; @@ -36,7 +38,6 @@ import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.java.*; import com.oracle.graal.nodes.spi.*; -import com.oracle.graal.nodes.type.*; import com.oracle.graal.nodes.util.*; import com.oracle.graal.options.*; import com.oracle.graal.phases.common.InliningUtil.InlineInfo; @@ -173,28 +174,30 @@ Mark markBeforeInlining = callerGraph.getMark(); InlineInfo callee = calleeInfo.callee(); try { - List invokeUsages = callee.invoke().asNode().usages().snapshot(); - callee.inline(new Providers(context), callerAssumptions); - callerAssumptions.record(calleeInfo.assumptions()); - metricInliningRuns.increment(); - Debug.dump(callerGraph, "after %s", callee); + try (Scope scope = Debug.scope("doInline", callerGraph)) { + List invokeUsages = callee.invoke().asNode().usages().snapshot(); + callee.inline(new Providers(context), callerAssumptions); + callerAssumptions.record(calleeInfo.assumptions()); + metricInliningRuns.increment(); + Debug.dump(callerGraph, "after %s", callee); - if (OptCanonicalizer.getValue()) { - Mark markBeforeCanonicalization = callerGraph.getMark(); - canonicalizer.applyIncremental(callerGraph, context, invokeUsages, markBeforeInlining); + if (OptCanonicalizer.getValue()) { + Mark markBeforeCanonicalization = callerGraph.getMark(); + canonicalizer.applyIncremental(callerGraph, context, invokeUsages, markBeforeInlining); - // process invokes that are possibly created during canonicalization - for (Node newNode : callerGraph.getNewNodes(markBeforeCanonicalization)) { - if (newNode instanceof Invoke) { - callerGraphInfo.pushInvoke((Invoke) newNode); + // process invokes that are possibly created during canonicalization + for (Node newNode : callerGraph.getNewNodes(markBeforeCanonicalization)) { + if (newNode instanceof Invoke) { + callerGraphInfo.pushInvoke((Invoke) newNode); + } } } - } + + callerGraphInfo.computeProbabilities(); - callerGraphInfo.computeProbabilities(); - - inliningCount++; - metricInliningPerformed.increment(); + inliningCount++; + metricInliningPerformed.increment(); + } } catch (BailoutException bailout) { throw bailout; } catch (AssertionError | RuntimeException e) { diff -r 3dde8d8c95b8 -r 40d0022115ee 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 Fri Apr 25 16:21:07 2014 +0200 +++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/InliningUtil.java Mon Apr 28 11:18:15 2014 +0200 @@ -24,11 +24,8 @@ import static com.oracle.graal.api.meta.DeoptimizationAction.*; import static com.oracle.graal.api.meta.DeoptimizationReason.*; -import static com.oracle.graal.nodes.type.StampFactory.*; -import static com.oracle.graal.phases.GraalOptions.*; -import static java.lang.reflect.Modifier.*; - -import java.lang.reflect.*; +import static com.oracle.graal.compiler.common.GraalOptions.*; +import static com.oracle.graal.compiler.common.type.StampFactory.*; import java.util.*; import com.oracle.graal.api.code.*; @@ -36,6 +33,9 @@ import com.oracle.graal.api.meta.*; import com.oracle.graal.api.meta.JavaTypeProfile.ProfiledType; import com.oracle.graal.api.meta.ResolvedJavaType.Representation; +import com.oracle.graal.compiler.common.*; +import com.oracle.graal.compiler.common.calc.*; +import com.oracle.graal.compiler.common.type.*; import com.oracle.graal.debug.*; import com.oracle.graal.debug.Debug.Scope; import com.oracle.graal.graph.*; @@ -137,13 +137,12 @@ */ private static void printInlining(final ResolvedJavaMethod method, final Invoke invoke, final int inliningDepth, final boolean success, final String msg, final Object... args) { if (HotSpotPrintInlining.getValue()) { - final int mod = method.getModifiers(); // 1234567 TTY.print(" "); // print timestamp // 1234 TTY.print(" "); // print compilation number // % s ! b n - TTY.print("%c%c%c%c%c ", ' ', Modifier.isSynchronized(mod) ? 's' : ' ', ' ', ' ', Modifier.isNative(mod) ? 'n' : ' '); + TTY.print("%c%c%c%c%c ", ' ', method.isSynchronized() ? 's' : ' ', ' ', ' ', method.isNative() ? 'n' : ' '); TTY.print(" "); // more indent TTY.print(" "); // initial inlining indent for (int i = 0; i < inliningDepth; i++) { @@ -432,7 +431,7 @@ super(invoke); this.concrete = concrete; this.type = type; - assert type.isArray() || !isAbstract(type.getModifiers()) : type; + assert type.isArray() || !type.isAbstract() : type; } @Override @@ -646,7 +645,7 @@ } // create one separate block for each invoked method - AbstractBeginNode[] successors = new AbstractBeginNode[numberOfMethods + 1]; + BeginNode[] successors = new BeginNode[numberOfMethods + 1]; for (int i = 0; i < numberOfMethods; i++) { successors[i] = createInvocationBlock(graph, invoke, returnMerge, returnValuePhi, exceptionMerge, exceptionObjectPhi, true); } @@ -658,7 +657,7 @@ } else { unknownTypeSux = graph.add(new DeoptimizeNode(DeoptimizationAction.InvalidateReprofile, DeoptimizationReason.TypeCheckedInliningViolated)); } - successors[successors.length - 1] = AbstractBeginNode.begin(unknownTypeSux); + successors[successors.length - 1] = BeginNode.begin(unknownTypeSux); // replace the invoke exception edge if (invoke instanceof InvokeWithExceptionNode) { @@ -684,7 +683,7 @@ // do the actual inlining for every invoke for (int i = 0; i < numberOfMethods; i++) { - AbstractBeginNode node = successors[i]; + BeginNode node = successors[i]; Invoke invokeForInlining = (Invoke) node.next(); ResolvedJavaType commonType; @@ -770,10 +769,10 @@ private void inlineSingleMethod(StructuredGraph graph, MetaAccessProvider metaAccess, Assumptions assumptions) { assert concretes.size() == 1 && inlineableElements.length == 1 && ptypes.size() > 1 && !shouldFallbackToInvoke() && notRecordedTypeProbability == 0; - AbstractBeginNode calleeEntryNode = graph.add(new BeginNode()); + BeginNode calleeEntryNode = graph.add(new BeginNode()); - AbstractBeginNode unknownTypeSux = createUnknownTypeSuccessor(graph); - AbstractBeginNode[] successors = new AbstractBeginNode[]{calleeEntryNode, unknownTypeSux}; + BeginNode unknownTypeSux = createUnknownTypeSuccessor(graph); + BeginNode[] successors = new BeginNode[]{calleeEntryNode, unknownTypeSux}; createDispatchOnTypeBeforeInvoke(graph, successors, false, metaAccess); calleeEntryNode.setNext(invoke.asNode()); @@ -781,7 +780,7 @@ inline(invoke, methodAt(0), inlineableElementAt(0), assumptions, false); } - private boolean createDispatchOnTypeBeforeInvoke(StructuredGraph graph, AbstractBeginNode[] successors, boolean invokeIsOnlySuccessor, MetaAccessProvider metaAccess) { + private boolean createDispatchOnTypeBeforeInvoke(StructuredGraph graph, BeginNode[] successors, boolean invokeIsOnlySuccessor, MetaAccessProvider metaAccess) { assert ptypes.size() >= 1; ValueNode nonNullReceiver = nonNullReceiver(invoke); Kind hubKind = ((MethodCallTargetNode) invoke.callTarget()).targetMethod().getDeclaringClass().getEncoding(Representation.ObjectHub).getKind(); @@ -891,10 +890,10 @@ return costEstimateMethodDispatch < costEstimateTypeDispatch; } - private static AbstractBeginNode createInvocationBlock(StructuredGraph graph, Invoke invoke, MergeNode returnMerge, PhiNode returnValuePhi, MergeNode exceptionMerge, - PhiNode exceptionObjectPhi, boolean useForInlining) { + private static BeginNode createInvocationBlock(StructuredGraph graph, Invoke invoke, MergeNode returnMerge, PhiNode returnValuePhi, MergeNode exceptionMerge, PhiNode exceptionObjectPhi, + boolean useForInlining) { Invoke duplicatedInvoke = duplicateInvokeForInlining(graph, invoke, exceptionMerge, exceptionObjectPhi, useForInlining); - AbstractBeginNode calleeEntryNode = graph.add(new BeginNode()); + BeginNode calleeEntryNode = graph.add(new BeginNode()); calleeEntryNode.setNext(duplicatedInvoke.asNode()); AbstractEndNode endNode = graph.add(new EndNode()); @@ -969,9 +968,9 @@ } private void devirtualizeWithTypeSwitch(StructuredGraph graph, InvokeKind kind, ResolvedJavaMethod target, MetaAccessProvider metaAccess) { - AbstractBeginNode invocationEntry = graph.add(new BeginNode()); - AbstractBeginNode unknownTypeSux = createUnknownTypeSuccessor(graph); - AbstractBeginNode[] successors = new AbstractBeginNode[]{invocationEntry, unknownTypeSux}; + BeginNode invocationEntry = graph.add(new BeginNode()); + BeginNode unknownTypeSux = createUnknownTypeSuccessor(graph); + BeginNode[] successors = new BeginNode[]{invocationEntry, unknownTypeSux}; createDispatchOnTypeBeforeInvoke(graph, successors, true, metaAccess); invocationEntry.setNext(invoke.asNode()); @@ -981,8 +980,8 @@ replaceInvokeCallTarget(invoke, graph, kind, target); } - private static AbstractBeginNode createUnknownTypeSuccessor(StructuredGraph graph) { - return AbstractBeginNode.begin(graph.add(new DeoptimizeNode(DeoptimizationAction.InvalidateReprofile, DeoptimizationReason.TypeCheckedInliningViolated))); + private static BeginNode createUnknownTypeSuccessor(StructuredGraph graph) { + return BeginNode.begin(graph.add(new DeoptimizeNode(DeoptimizationAction.InvalidateReprofile, DeoptimizationReason.TypeCheckedInliningViolated))); } @Override @@ -1111,7 +1110,7 @@ private static InlineInfo getAssumptionInlineInfo(InliningData data, Invoke invoke, Replacements replacements, OptimisticOptimizations optimisticOpts, ResolvedJavaMethod concrete, Assumption takenAssumption) { - assert !Modifier.isAbstract(concrete.getModifiers()); + assert !concrete.isAbstract(); if (!checkTargetConditions(data, replacements, invoke, concrete, optimisticOpts)) { return null; } @@ -1119,7 +1118,7 @@ } private static InlineInfo getExactInlineInfo(InliningData data, Invoke invoke, Replacements replacements, OptimisticOptimizations optimisticOpts, ResolvedJavaMethod targetMethod) { - assert !Modifier.isAbstract(targetMethod.getModifiers()); + assert !targetMethod.isAbstract(); if (!checkTargetConditions(data, replacements, invoke, targetMethod, optimisticOpts)) { return null; } @@ -1149,7 +1148,7 @@ } ResolvedJavaType type = ptypes[0].getType(); - assert type.isArray() || !isAbstract(type.getModifiers()); + assert type.isArray() || !type.isAbstract(); ResolvedJavaMethod concrete = type.resolveMethod(targetMethod); if (!checkTargetConditions(data, replacements, invoke, concrete, optimisticOpts)) { return null; @@ -1221,7 +1220,7 @@ if (index == -1) { notRecordedTypeProbability += type.getProbability(); } else { - assert type.getType().isArray() || !isAbstract(type.getType().getModifiers()) : type + " " + concrete; + assert type.getType().isArray() || !type.getType().isAbstract() : type + " " + concrete; usedTypes.add(type); typesToConcretes.add(index); } @@ -1274,9 +1273,9 @@ private static boolean checkTargetConditions(InliningData data, Replacements replacements, Invoke invoke, ResolvedJavaMethod method, OptimisticOptimizations optimisticOpts) { if (method == null) { return logNotInlinedMethodAndReturnFalse(invoke, data.inliningDepth(), method, "the method is not resolved"); - } else if (Modifier.isNative(method.getModifiers()) && (!Intrinsify.getValue() || !InliningUtil.canIntrinsify(replacements, method))) { + } else if (method.isNative() && (!Intrinsify.getValue() || !InliningUtil.canIntrinsify(replacements, method))) { return logNotInlinedMethodAndReturnFalse(invoke, data.inliningDepth(), method, "it is a non-intrinsic native method"); - } else if (Modifier.isAbstract(method.getModifiers())) { + } else if (method.isAbstract()) { return logNotInlinedMethodAndReturnFalse(invoke, data.inliningDepth(), method, "it is an abstract method"); } else if (!method.getDeclaringClass().isInitialized()) { return logNotInlinedMethodAndReturnFalse(invoke, data.inliningDepth(), method, "the method's class is not initialized"); @@ -1317,8 +1316,6 @@ assert inlineGraph.getGuardsStage().ordinal() >= graph.getGuardsStage().ordinal(); assert !invokeNode.graph().isAfterFloatingReadPhase() : "inline isn't handled correctly after floating reads phase"; - Kind returnKind = invokeNode.getKind(); - FrameState stateAfter = invoke.stateAfter(); assert stateAfter == null || stateAfter.isAlive(); if (receiverNullCheck && !((MethodCallTargetNode) invoke.callTarget()).isStatic()) { @@ -1347,7 +1344,7 @@ } } - final AbstractBeginNode prevBegin = AbstractBeginNode.prevBegin(invokeNode); + final BeginNode prevBegin = BeginNode.prevBegin(invokeNode); DuplicationReplacement localReplacement = new DuplicationReplacement() { public Node replacement(Node node) { @@ -1386,7 +1383,7 @@ } // get rid of memory kill - AbstractBeginNode begin = invokeWithException.next(); + BeginNode begin = invokeWithException.next(); if (begin instanceof KillingBeginNode) { BeginNode newBegin = new BeginNode(); graph.addAfterFixed(begin, graph.add(newBegin)); @@ -1396,52 +1393,14 @@ } else { if (unwindNode != null) { UnwindNode unwindDuplicate = (UnwindNode) duplicates.get(unwindNode); - MonitorExitNode monitorExit = findPrecedingMonitorExit(unwindDuplicate); - DeoptimizeNode deoptimizeNode = new DeoptimizeNode(DeoptimizationAction.InvalidateRecompile, DeoptimizationReason.NotCompiledExceptionHandler); - unwindDuplicate.replaceAndDelete(graph.add(deoptimizeNode)); - // move the deopt upwards if there is a monitor exit that tries to use the - // "after exception" frame state - // (because there is no "after exception" frame state!) - if (monitorExit != null) { - if (monitorExit.stateAfter() != null && monitorExit.stateAfter().bci == FrameState.AFTER_EXCEPTION_BCI) { - FrameState monitorFrameState = monitorExit.stateAfter(); - graph.removeFixed(monitorExit); - monitorFrameState.safeDelete(); - } - } + DeoptimizeNode deoptimizeNode = graph.add(new DeoptimizeNode(DeoptimizationAction.InvalidateRecompile, DeoptimizationReason.NotCompiledExceptionHandler)); + unwindDuplicate.replaceAndDelete(deoptimizeNode); } } if (stateAfter != null) { - FrameState outerFrameState = null; + processFrameStates(invoke, inlineGraph, duplicates, stateAtExceptionEdge); int callerLockDepth = stateAfter.nestedLockDepth(); - for (FrameState original : inlineGraph.getNodes(FrameState.class)) { - FrameState frameState = (FrameState) duplicates.get(original); - if (frameState != null) { - assert frameState.bci != FrameState.BEFORE_BCI : frameState; - if (frameState.bci == FrameState.AFTER_BCI) { - frameState.replaceAndDelete(returnKind == Kind.Void ? stateAfter : stateAfter.duplicateModified(stateAfter.bci, stateAfter.rethrowException(), returnKind, - frameState.stackAt(0))); - } else if (frameState.bci == FrameState.AFTER_EXCEPTION_BCI) { - if (frameState.isAlive()) { - assert stateAtExceptionEdge != null; - frameState.replaceAndDelete(stateAtExceptionEdge); - } else { - assert stateAtExceptionEdge == null; - } - } else { - // only handle the outermost frame states - if (frameState.outerFrameState() == null) { - assert frameState.bci == FrameState.INVALID_FRAMESTATE_BCI || frameState.method().equals(inlineGraph.method()); - if (outerFrameState == null) { - outerFrameState = stateAfter.duplicateModified(invoke.bci(), stateAfter.rethrowException(), invokeNode.getKind()); - outerFrameState.setDuringCall(true); - } - frameState.setOuterFrameState(outerFrameState); - } - } - } - } if (callerLockDepth != 0) { for (MonitorIdNode original : inlineGraph.getNodes(MonitorIdNode.class)) { MonitorIdNode monitor = (MonitorIdNode) duplicates.get(original); @@ -1479,6 +1438,93 @@ return duplicates; } + protected static void processFrameStates(Invoke invoke, StructuredGraph inlineGraph, Map duplicates, FrameState stateAtExceptionEdge) { + FrameState stateAtReturn = invoke.stateAfter(); + FrameState outerFrameState = null; + Kind invokeReturnKind = invoke.asNode().getKind(); + for (FrameState original : inlineGraph.getNodes(FrameState.class)) { + FrameState frameState = (FrameState) duplicates.get(original); + if (frameState != null && frameState.isAlive()) { + if (frameState.bci == BytecodeFrame.AFTER_BCI) { + /* + * pop return kind from invoke's stateAfter and replace with this frameState's + * return value (top of stack) + */ + FrameState stateAfterReturn = stateAtReturn; + if (invokeReturnKind != Kind.Void && frameState.stackSize() > 0 && stateAfterReturn.stackAt(0) != frameState.stackAt(0)) { + stateAfterReturn = stateAtReturn.duplicateModified(invokeReturnKind, frameState.stackAt(0)); + } + frameState.replaceAndDelete(stateAfterReturn); + } else if (stateAtExceptionEdge != null && isStateAfterException(frameState)) { + /* + * pop exception object from invoke's stateAfter and replace with this + * frameState's exception object (top of stack) + */ + FrameState stateAfterException = stateAtExceptionEdge; + if (frameState.stackSize() > 0 && stateAtExceptionEdge.stackAt(0) != frameState.stackAt(0)) { + stateAfterException = stateAtExceptionEdge.duplicateModified(Kind.Object, frameState.stackAt(0)); + } + frameState.replaceAndDelete(stateAfterException); + } else if (frameState.bci == BytecodeFrame.UNWIND_BCI || frameState.bci == BytecodeFrame.AFTER_EXCEPTION_BCI) { + handleMissingAfterExceptionFrameState(frameState); + } else { + // only handle the outermost frame states + if (frameState.outerFrameState() == null) { + assert frameState.bci != BytecodeFrame.BEFORE_BCI : frameState; + assert frameState.bci == BytecodeFrame.INVALID_FRAMESTATE_BCI || frameState.method().equals(inlineGraph.method()); + assert frameState.bci != BytecodeFrame.AFTER_EXCEPTION_BCI && frameState.bci != BytecodeFrame.BEFORE_BCI && frameState.bci != BytecodeFrame.AFTER_EXCEPTION_BCI && + frameState.bci != BytecodeFrame.UNWIND_BCI : frameState.bci; + if (outerFrameState == null) { + outerFrameState = stateAtReturn.duplicateModified(invoke.bci(), stateAtReturn.rethrowException(), invokeReturnKind); + outerFrameState.setDuringCall(true); + } + frameState.setOuterFrameState(outerFrameState); + } + } + } + } + } + + private static boolean isStateAfterException(FrameState frameState) { + return frameState.bci == BytecodeFrame.AFTER_EXCEPTION_BCI || (frameState.bci == BytecodeFrame.UNWIND_BCI && !frameState.method().isSynchronized()); + } + + protected static void handleMissingAfterExceptionFrameState(FrameState nonReplaceableFrameState) { + Graph graph = nonReplaceableFrameState.graph(); + NodeWorkList workList = graph.createNodeWorkList(); + workList.add(nonReplaceableFrameState); + for (Node node : workList) { + FrameState fs = (FrameState) node; + for (Node usage : fs.usages().snapshot()) { + if (!usage.isAlive()) { + continue; + } + if (usage instanceof FrameState) { + workList.add(usage); + } else { + StateSplit stateSplit = (StateSplit) usage; + FixedNode fixedStateSplit = stateSplit.asNode(); + if (fixedStateSplit instanceof MergeNode) { + MergeNode merge = (MergeNode) fixedStateSplit; + while (merge.isAlive()) { + AbstractEndNode end = merge.forwardEnds().first(); + DeoptimizeNode deoptimizeNode = graph.add(new DeoptimizeNode(DeoptimizationAction.InvalidateRecompile, DeoptimizationReason.NotCompiledExceptionHandler)); + end.replaceAtPredecessor(deoptimizeNode); + GraphUtil.killCFG(end); + } + } else { + FixedNode deoptimizeNode = graph.add(new DeoptimizeNode(DeoptimizationAction.InvalidateRecompile, DeoptimizationReason.NotCompiledExceptionHandler)); + if (fixedStateSplit instanceof BeginNode) { + deoptimizeNode = BeginNode.begin(deoptimizeNode); + } + fixedStateSplit.replaceAtPredecessor(deoptimizeNode); + GraphUtil.killCFG(fixedStateSplit); + } + } + } + } + } + public static ValueNode mergeReturns(MergeNode merge, List returnNodes) { PhiNode returnValuePhi = null; @@ -1504,7 +1550,7 @@ for (Node node : duplicates.values()) { if (node instanceof FrameState) { FrameState frameState = (FrameState) node; - assert frameState.bci == FrameState.AFTER_BCI || frameState.bci == FrameState.INVALID_FRAMESTATE_BCI : node.toString(Verbosity.Debugger); + assert frameState.bci == BytecodeFrame.AFTER_BCI || frameState.bci == BytecodeFrame.INVALID_FRAMESTATE_BCI : node.toString(Verbosity.Debugger); } } return true; @@ -1518,7 +1564,7 @@ assert !callTarget.isStatic() : callTarget.targetMethod(); StructuredGraph graph = callTarget.graph(); ValueNode firstParam = callTarget.arguments().get(0); - if (firstParam.getKind() == Kind.Object && !ObjectStamp.isObjectNonNull(firstParam)) { + if (firstParam.getKind() == Kind.Object && !StampTool.isObjectNonNull(firstParam)) { IsNullNode condition = graph.unique(new IsNullNode(firstParam)); Stamp stamp = firstParam.stamp().join(objectNonNull()); GuardingPiNode nonNullReceiver = graph.add(new GuardingPiNode(firstParam, condition, true, NullCheckException, InvalidateReprofile, stamp)); @@ -1566,7 +1612,7 @@ try { return macroNodeClass.getConstructor(Invoke.class).newInstance(invoke); } catch (ReflectiveOperationException | IllegalArgumentException | SecurityException e) { - throw new GraalInternalError(e).addContext(invoke.asNode()).addContext("macroSubstitution", macroNodeClass); + throw new GraalGraphInternalError(e).addContext(invoke.asNode()).addContext("macroSubstitution", macroNodeClass); } } } diff -r 3dde8d8c95b8 -r 40d0022115ee 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 Fri Apr 25 16:21:07 2014 +0200 +++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/IterativeConditionalEliminationPhase.java Mon Apr 28 11:18:15 2014 +0200 @@ -62,7 +62,7 @@ canonicalizer.applyIncremental(graph, context, listener.getChangedNodes()); listener.getChangedNodes().clear(); if (++count > MAX_ITERATIONS) { - throw new BailoutException("Number of iterations in conditional elimination phase exceeds " + MAX_ITERATIONS); + throw new BailoutException("Number of iterations in ConditionalEliminationPhase phase exceeds " + MAX_ITERATIONS); } } } diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/LoopSafepointInsertionPhase.java --- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/LoopSafepointInsertionPhase.java Fri Apr 25 16:21:07 2014 +0200 +++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/LoopSafepointInsertionPhase.java Mon Apr 28 11:18:15 2014 +0200 @@ -22,7 +22,7 @@ */ package com.oracle.graal.phases.common; -import static com.oracle.graal.phases.GraalOptions.*; +import static com.oracle.graal.compiler.common.GraalOptions.*; import com.oracle.graal.nodes.*; import com.oracle.graal.phases.*; diff -r 3dde8d8c95b8 -r 40d0022115ee 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 Fri Apr 25 16:21:07 2014 +0200 +++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/LoweringPhase.java Mon Apr 28 11:18:15 2014 +0200 @@ -22,12 +22,13 @@ */ package com.oracle.graal.phases.common; -import static com.oracle.graal.phases.GraalOptions.*; +import static com.oracle.graal.compiler.common.GraalOptions.*; import java.util.*; import com.oracle.graal.api.code.*; import com.oracle.graal.api.meta.*; +import com.oracle.graal.compiler.common.type.*; import com.oracle.graal.graph.Graph.Mark; import com.oracle.graal.graph.*; import com.oracle.graal.graph.iterators.*; @@ -36,7 +37,6 @@ import com.oracle.graal.nodes.cfg.*; import com.oracle.graal.nodes.extended.*; import com.oracle.graal.nodes.spi.*; -import com.oracle.graal.nodes.type.*; import com.oracle.graal.phases.*; import com.oracle.graal.phases.schedule.*; import com.oracle.graal.phases.tiers.*; diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/NonNullParametersPhase.java --- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/NonNullParametersPhase.java Fri Apr 25 16:21:07 2014 +0200 +++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/NonNullParametersPhase.java Mon Apr 28 11:18:15 2014 +0200 @@ -22,8 +22,8 @@ */ package com.oracle.graal.phases.common; +import com.oracle.graal.compiler.common.type.*; import com.oracle.graal.nodes.*; -import com.oracle.graal.nodes.type.*; import com.oracle.graal.phases.*; /** diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/OptimizeGuardAnchorsPhase.java --- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/OptimizeGuardAnchorsPhase.java Fri Apr 25 16:21:07 2014 +0200 +++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/OptimizeGuardAnchorsPhase.java Mon Apr 28 11:18:15 2014 +0200 @@ -55,11 +55,11 @@ @Override protected void run(StructuredGraph graph) { LazyCFG cfg = new LazyCFG(graph); - for (AbstractBeginNode begin : graph.getNodes(AbstractBeginNode.class)) { + for (BeginNode begin : graph.getNodes(BeginNode.class)) { if (!(begin instanceof StartNode || begin.predecessor() instanceof ControlSplitNode)) { NodeIterable guards = begin.guards(); if (guards.isNotEmpty()) { - AbstractBeginNode newAnchor = computeOptimalAnchor(cfg.get(), begin); + BeginNode newAnchor = computeOptimalAnchor(cfg.get(), begin); // newAnchor == begin is possible because postdominator computation assumes that // loops never end if (newAnchor != begin) { @@ -76,14 +76,14 @@ } } - public static AbstractBeginNode getOptimalAnchor(LazyCFG cfg, AbstractBeginNode begin) { + public static BeginNode getOptimalAnchor(LazyCFG cfg, BeginNode begin) { if (begin instanceof StartNode || begin.predecessor() instanceof ControlSplitNode) { return begin; } return computeOptimalAnchor(cfg.get(), begin); } - private static AbstractBeginNode computeOptimalAnchor(ControlFlowGraph cfg, AbstractBeginNode begin) { + private static BeginNode computeOptimalAnchor(ControlFlowGraph cfg, BeginNode begin) { Block anchor = cfg.blockFor(begin); while (anchor.getDominator() != null && anchor.getDominator().getPostdominator() == anchor) { anchor = anchor.getDominator(); @@ -92,7 +92,7 @@ } private static void optimizeAtControlSplit(ControlSplitNode controlSplit, LazyCFG cfg) { - AbstractBeginNode successor = findMinimumUsagesSuccessor(controlSplit); + BeginNode successor = findMinimumUsagesSuccessor(controlSplit); int successorCount = controlSplit.successors().count(); List otherGuards = new ArrayList<>(successorCount - 1); for (GuardNode guard : successor.guards().snapshot()) { @@ -109,7 +109,7 @@ } if (otherGuards.size() == successorCount - 1) { - AbstractBeginNode anchor = computeOptimalAnchor(cfg.get(), AbstractBeginNode.prevBegin(controlSplit)); + BeginNode anchor = computeOptimalAnchor(cfg.get(), BeginNode.prevBegin(controlSplit)); GuardNode newGuard = controlSplit.graph().unique(new GuardNode(guard.condition(), anchor, guard.reason(), guard.action(), guard.negated(), guard.getSpeculation())); for (GuardNode otherGuard : otherGuards) { otherGuard.replaceAndDelete(newGuard); @@ -126,12 +126,12 @@ conditonGuard.getSpeculation().equals(guard.getSpeculation()); } - private static AbstractBeginNode findMinimumUsagesSuccessor(ControlSplitNode controlSplit) { + private static BeginNode findMinimumUsagesSuccessor(ControlSplitNode controlSplit) { NodeClassIterator successors = controlSplit.successors().iterator(); - AbstractBeginNode min = (AbstractBeginNode) successors.next(); + BeginNode min = (BeginNode) successors.next(); int minUsages = min.usages().count(); while (successors.hasNext()) { - AbstractBeginNode successor = (AbstractBeginNode) successors.next(); + BeginNode successor = (BeginNode) successors.next(); int count = successor.usages().count(); if (count < minUsages) { minUsages = count; diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/ProfileCompiledMethodsPhase.java --- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/ProfileCompiledMethodsPhase.java Fri Apr 25 16:21:07 2014 +0200 +++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/ProfileCompiledMethodsPhase.java Mon Apr 28 11:18:15 2014 +0200 @@ -24,6 +24,7 @@ import java.util.*; +import com.oracle.graal.compiler.common.cfg.*; import com.oracle.graal.graph.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.calc.*; @@ -43,19 +44,22 @@ * for each node would be too costly, so this phase takes the compromise that it trusts split * probabilities, but not loop frequencies. This means that it will insert counters at the start of * a method and at each loop header. - * + * * A schedule is created so that floating nodes can also be taken into account. The weight of a node * is determined heuristically in the * {@link ProfileCompiledMethodsPhase#getNodeWeight(ScheduledNode)} method. - * + * * Additionally, there's a second counter that's only increased for code sections without invokes. */ public class ProfileCompiledMethodsPhase extends Phase { private static final String GROUP_NAME = "~profiled weight"; private static final String GROUP_NAME_WITHOUT = "~profiled weight (invoke-free sections)"; + private static final String GROUP_NAME_INVOKES = "~profiled invokes"; private static final boolean WITH_SECTION_HEADER = false; + private static boolean WITH_INVOKE_FREE_SECTIONS = false; + private static boolean WITH_INVOKES = true; @Override protected void run(StructuredGraph graph) { @@ -65,23 +69,38 @@ schedule.apply(graph, false); ControlFlowGraph cfg = ControlFlowGraph.compute(graph, true, true, true, true); - for (Loop loop : cfg.getLoops()) { - double loopProbability = probabilities.get(loop.loopBegin()); + for (Loop loop : cfg.getLoops()) { + double loopProbability = probabilities.get(loop.header.getBeginNode()); if (loopProbability > (1D / Integer.MAX_VALUE)) { - addSectionCounters(loop.loopBegin(), loop.blocks, loop.children, schedule, probabilities); + addSectionCounters(loop.header.getBeginNode(), loop.blocks, loop.children, schedule, probabilities); } } - addSectionCounters(graph.start(), Arrays.asList(cfg.getBlocks()), Arrays.asList(cfg.getLoops()), schedule, probabilities); + // don't put the counter increase directly after the start (problems with OSR) + FixedWithNextNode current = graph.start(); + while (current.next() instanceof FixedWithNextNode) { + current = (FixedWithNextNode) current.next(); + } + addSectionCounters(current, Arrays.asList(cfg.getBlocks()), cfg.getLoops(), schedule, probabilities); + + if (WITH_INVOKES) { + for (Node node : graph.getNodes()) { + if (node instanceof Invoke) { + Invoke invoke = (Invoke) node; + DynamicCounterNode.addCounterBefore(GROUP_NAME_INVOKES, invoke.callTarget().targetName(), 1, true, invoke.asNode()); + + } + } + } } - private static void addSectionCounters(FixedWithNextNode start, Collection sectionBlocks, Collection childLoops, SchedulePhase schedule, NodesToDoubles probabilities) { + private static void addSectionCounters(FixedWithNextNode start, Collection sectionBlocks, Collection> childLoops, SchedulePhase schedule, NodesToDoubles probabilities) { HashSet blocks = new HashSet<>(sectionBlocks); - for (Loop loop : childLoops) { + for (Loop loop : childLoops) { blocks.removeAll(loop.blocks); } double weight = getSectionWeight(schedule, probabilities, blocks) / probabilities.get(start); DynamicCounterNode.addCounterBefore(GROUP_NAME, sectionHead(start), (long) weight, true, start.next()); - if (!hasInvoke(blocks)) { + if (WITH_INVOKE_FREE_SECTIONS && !hasInvoke(blocks)) { DynamicCounterNode.addCounterBefore(GROUP_NAME_WITHOUT, sectionHead(start), (long) weight, true, start.next()); } } @@ -108,7 +127,7 @@ private static double getNodeWeight(ScheduledNode node) { if (node instanceof MergeNode) { return ((MergeNode) node).phiPredecessorCount(); - } else if (node instanceof AbstractBeginNode || node instanceof AbstractEndNode || node instanceof MonitorIdNode || node instanceof ConstantNode || node instanceof ParameterNode || + } else if (node instanceof BeginNode || node instanceof AbstractEndNode || node instanceof MonitorIdNode || node instanceof ConstantNode || node instanceof ParameterNode || node instanceof CallTargetNode || node instanceof ValueProxy || node instanceof VirtualObjectNode || node instanceof ReinterpretNode) { return 0; } else if (node instanceof AccessMonitorNode) { diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/ReadEliminationPhase.java --- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/ReadEliminationPhase.java Fri Apr 25 16:21:07 2014 +0200 +++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/ReadEliminationPhase.java Mon Apr 28 11:18:15 2014 +0200 @@ -22,6 +22,7 @@ */ package com.oracle.graal.phases.common; +import com.oracle.graal.compiler.common.*; import com.oracle.graal.debug.*; import com.oracle.graal.graph.*; import com.oracle.graal.nodes.*; diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/TailDuplicationPhase.java --- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/TailDuplicationPhase.java Fri Apr 25 16:21:07 2014 +0200 +++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/TailDuplicationPhase.java Mon Apr 28 11:18:15 2014 +0200 @@ -22,10 +22,12 @@ */ package com.oracle.graal.phases.common; -import static com.oracle.graal.phases.GraalOptions.*; +import static com.oracle.graal.compiler.common.GraalOptions.*; import java.util.*; +import com.oracle.graal.compiler.common.*; +import com.oracle.graal.compiler.common.type.*; import com.oracle.graal.debug.*; import com.oracle.graal.graph.Graph.DuplicationReplacement; import com.oracle.graal.graph.Graph.Mark; @@ -37,7 +39,6 @@ import com.oracle.graal.nodes.extended.*; import com.oracle.graal.nodes.java.*; import com.oracle.graal.nodes.spi.*; -import com.oracle.graal.nodes.type.*; import com.oracle.graal.nodes.util.*; import com.oracle.graal.nodes.virtual.*; import com.oracle.graal.phases.*; @@ -293,7 +294,7 @@ // EndNode FixedWithNextNode anchorDuplicate = (FixedWithNextNode) duplicates.get(anchor); // move dependencies on the ValueAnchorNode to the previous BeginNode - AbstractBeginNode prevBegin = AbstractBeginNode.prevBegin(forwardEnd); + BeginNode prevBegin = BeginNode.prevBegin(forwardEnd); anchorDuplicate.replaceAtUsages(InputType.Guard, prevBegin); anchorDuplicate.replaceAtUsages(InputType.Anchor, prevBegin); assert anchorDuplicate.usages().isEmpty(); diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/UseTrappingNullChecksPhase.java --- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/UseTrappingNullChecksPhase.java Fri Apr 25 16:21:07 2014 +0200 +++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/UseTrappingNullChecksPhase.java Mon Apr 28 11:18:15 2014 +0200 @@ -55,7 +55,7 @@ } Node predecessor = deopt.predecessor(); Node branch = null; - while (predecessor instanceof AbstractBeginNode) { + while (predecessor instanceof BeginNode) { branch = predecessor; predecessor = predecessor.predecessor(); } @@ -73,8 +73,8 @@ private static void replaceWithTrappingNullCheck(DeoptimizeNode deopt, IfNode ifNode, LogicNode condition) { IsNullNode isNullNode = (IsNullNode) condition; - AbstractBeginNode nonTrappingContinuation = ifNode.falseSuccessor(); - AbstractBeginNode trappingContinuation = ifNode.trueSuccessor(); + BeginNode nonTrappingContinuation = ifNode.falseSuccessor(); + BeginNode trappingContinuation = ifNode.trueSuccessor(); NullCheckNode trappingNullCheck = deopt.graph().add(new NullCheckNode(isNullNode.object())); trappingNullCheck.setStateBefore(deopt.stateBefore()); deopt.graph().replaceSplit(ifNode, trappingNullCheck, nonTrappingContinuation); diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/cfs/BaseReduction.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/cfs/BaseReduction.java Mon Apr 28 11:18:15 2014 +0200 @@ -0,0 +1,233 @@ +/* + * 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.phases.common.cfs; + +import com.oracle.graal.api.code.Assumptions; +import com.oracle.graal.api.meta.*; +import com.oracle.graal.debug.Debug; +import com.oracle.graal.debug.DebugMetric; +import com.oracle.graal.graph.Node; +import com.oracle.graal.graph.spi.CanonicalizerTool; +import com.oracle.graal.nodes.*; +import com.oracle.graal.compiler.common.type.ObjectStamp; +import com.oracle.graal.phases.graph.PostOrderNodeIterator; +import com.oracle.graal.phases.tiers.PhaseContext; + +import java.util.ArrayList; + +/** + *

+ * For readability purposes the code realizing control-flow-sensitive reductions is chopped into + * several classes in an inheritance hierarchy, this class being their common ancestor. That way, + * many dependencies can be ruled out immediately (e.g., private members of a class aren't needed by + * other classes). The whole thing is reminiscent of trait-based patterns, minus their + * disadvantages. + *

+ * + * + *

+ * This class makes available little more than a few fields and a few utility methods used + * throughout the remaining components making up control-flow sensitive reductions. + *

+ * */ +public abstract class BaseReduction extends PostOrderNodeIterator { + + protected static final DebugMetric metricCheckCastRemoved = Debug.metric("CheckCastRemoved"); + protected static final DebugMetric metricGuardingPiNodeRemoved = Debug.metric("GuardingPiNodeRemoved"); + protected static final DebugMetric metricFixedGuardNodeRemoved = Debug.metric("FixedGuardNodeRemoved"); + protected static final DebugMetric metricMethodResolved = Debug.metric("MethodResolved"); + + /** + *

+ * Upon visiting a {@link com.oracle.graal.nodes.FixedNode FixedNode} in + * {@link #node(com.oracle.graal.nodes.FixedNode)}, an impossible path may be detected. We'd + * like to insert an unconditional deoptimizing node as a hint for Dead Code Elimination to kill + * that branch. However that can't be made on the go (a + * {@link com.oracle.graal.nodes.ControlSinkNode} can't have successors). Thus their insertion + * is postponed till the end of a round of + * {@link com.oracle.graal.phases.common.cfs.FlowSensitiveReduction}. + *

+ * + * @see State#impossiblePath() + * @see com.oracle.graal.phases.common.cfs.FlowSensitiveReduction#finished() + * */ + public static class PostponedDeopt { + + private final boolean goesBeforeFixed; + private final FixedWithNextNode fixed; + private final DeoptimizationReason deoptReason; + + public PostponedDeopt(boolean goesBeforeFixed, FixedWithNextNode fixed, DeoptimizationReason deoptReason) { + this.goesBeforeFixed = goesBeforeFixed; + this.fixed = fixed; + this.deoptReason = deoptReason; + } + + public void doRewrite(LogicNode falseConstant) { + StructuredGraph graph = fixed.graph(); + // have to insert a FixedNode other than a ControlSinkNode + FixedGuardNode buckStopsHere = graph.add(new FixedGuardNode(falseConstant, deoptReason, DeoptimizationAction.None)); + if (goesBeforeFixed) { + fixed.replaceAtPredecessor(buckStopsHere); + } else { + graph.addAfterFixed(fixed, buckStopsHere); + } + } + + } + + protected static class PostponedDeopts extends ArrayList { + + private static final long serialVersionUID = 7188324432387121238L; + + /** + * Enqueue adding a {@link com.oracle.graal.nodes.DeoptimizeNode} right before the fixed + * argument, will be done once we're done traversing the graph. + * + * @see #finished() + * */ + void addDeoptBefore(FixedWithNextNode fixed, DeoptimizationReason deoptReason) { + add(new PostponedDeopt(true, fixed, deoptReason)); + } + + /** + * Enqueue adding a {@link com.oracle.graal.nodes.DeoptimizeNode} right after the fixed + * argument, will be done once we're done traversing the graph. + * + * @see #finished() + * */ + void addDeoptAfter(FixedWithNextNode fixed, DeoptimizationReason deoptReason) { + add(new PostponedDeopt(false, fixed, deoptReason)); + } + + } + + /** + *

+ * One of the promises of + * {@link com.oracle.graal.phases.common.cfs.EquationalReasoner#deverbosify(com.oracle.graal.graph.Node)} + * is that a "maximally reduced" node is returned. That is achieved in part by leveraging + * {@link com.oracle.graal.graph.Node#canonical(com.oracle.graal.graph.spi.CanonicalizerTool)}. + * Doing so, in turn, requires this subclass of + * {@link com.oracle.graal.graph.spi.CanonicalizerTool}. + *

+ * */ + public final class Tool implements CanonicalizerTool { + + private final PhaseContext context; + + public Tool(PhaseContext context) { + this.context = context; + } + + @Override + public Assumptions assumptions() { + return context.getAssumptions(); + } + + @Override + public MetaAccessProvider getMetaAccess() { + return context.getMetaAccess(); + } + + @Override + public ConstantReflectionProvider getConstantReflection() { + return context.getConstantReflection(); + } + + /** + * Postpone + * {@link com.oracle.graal.nodes.util.GraphUtil#tryKillUnused(com.oracle.graal.graph.Node)} + * until {@link FlowSensitiveReduction#finished()} for the reasons covered there. + * */ + @Override + public void removeIfUnused(Node node) { + // GraphUtil.tryKillUnused(node); + } + + @Override + public boolean canonicalizeReads() { + return false; + } + } // end of class FlowSensitiveReduction.Tool + + protected final LogicConstantNode trueConstant; + protected final LogicConstantNode falseConstant; + protected final ConstantNode nullConstant; + + protected final CanonicalizerTool tool; + protected final StructuredGraph graph; + + protected EquationalReasoner reasoner; + + protected final PostponedDeopts postponedDeopts = new PostponedDeopts(); + + protected BaseReduction(FixedNode start, State initialState, PhaseContext context) { + super(start, initialState); + graph = start.graph(); + trueConstant = LogicConstantNode.tautology(graph); + falseConstant = LogicConstantNode.contradiction(graph); + nullConstant = ConstantNode.defaultForKind(Kind.Object, graph); // ConstantNode.forObject(null, + // metaAccess, graph); + tool = new Tool(context); + reasoner = new EquationalReasoner(graph, tool, trueConstant, falseConstant, nullConstant); + } + + /** + *

+ * Test whether the output's stamp is an upcast of that of the input. For example, upon + * replacing a CheckCastNode in + * {@link com.oracle.graal.phases.common.cfs.FlowSensitiveReduction#lowerCheckCastAnchorFriendlyWay(com.oracle.graal.nodes.java.CheckCastNode, com.oracle.graal.nodes.ValueNode)} + * we don't want to be left with an upcast, as it loses precision. + *

+ * + *

+ * As usual with object stamps, they can be compared along different dimensions (alwaysNull, + * etc.) It's enough for one such dimension to show precision loss for the end result to be + * reported as such. + *

+ * + * */ + protected static boolean precisionLoss(ValueNode input, ValueNode output) { + ObjectStamp inputStamp = (ObjectStamp) input.stamp(); + ObjectStamp outputStamp = (ObjectStamp) output.stamp(); + if (FlowUtil.isMorePrecise(inputStamp.type(), outputStamp.type())) { + return true; + } + if (lessThan(outputStamp.alwaysNull(), inputStamp.alwaysNull())) { + return true; + } + if (lessThan(outputStamp.nonNull(), inputStamp.nonNull())) { + return true; + } + if (lessThan(outputStamp.isExactType(), inputStamp.isExactType())) { + return true; + } + return false; + } + + private static boolean lessThan(boolean a, boolean b) { + return a == false && b == true; + } + +} diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/cfs/CastCheckExtractor.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/cfs/CastCheckExtractor.java Mon Apr 28 11:18:15 2014 +0200 @@ -0,0 +1,87 @@ +/* + * 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.phases.common.cfs; + +import com.oracle.graal.api.meta.ResolvedJavaType; +import com.oracle.graal.nodes.LogicNode; +import com.oracle.graal.nodes.ShortCircuitOrNode; +import com.oracle.graal.nodes.ValueNode; +import com.oracle.graal.nodes.calc.IsNullNode; +import com.oracle.graal.nodes.java.InstanceOfNode; + +/** + * @see #extract(com.oracle.graal.nodes.LogicNode) + * */ +class CastCheckExtractor { + + public final ResolvedJavaType type; + public final ValueNode subject; + + CastCheckExtractor(ResolvedJavaType type, ValueNode subject) { + this.type = type; + this.subject = subject; + } + + static CastCheckExtractor extractCastCheckInfo(LogicNode x, LogicNode y) { + if (x instanceof IsNullNode) { + IsNullNode isNull = (IsNullNode) x; + ValueNode subject = isNull.object(); + if (isInstanceOfCheckOn(y, subject)) { + InstanceOfNode iOf = (InstanceOfNode) y; + return new CastCheckExtractor(iOf.type(), subject); + } + } + return null; + } + + /** + * This method detects whether the argument realizes the CheckCast pattern. If so, distills and + * returns the essentials of such check, otherwise returns null. + * */ + static CastCheckExtractor extract(LogicNode cond) { + if (!(cond instanceof ShortCircuitOrNode)) { + return null; + } + ShortCircuitOrNode orNode = (ShortCircuitOrNode) cond; + if (orNode.isXNegated() || orNode.isYNegated()) { + return null; + } + CastCheckExtractor result = extractCastCheckInfo(orNode.getX(), orNode.getY()); + if (result != null) { + return result; + } + result = extractCastCheckInfo(orNode.getY(), orNode.getX()); + return result; + } + + /** + * Porcelain method. + * */ + public static boolean isInstanceOfCheckOn(LogicNode cond, ValueNode subject) { + if (!(cond instanceof InstanceOfNode)) { + return false; + } + InstanceOfNode io = (InstanceOfNode) cond; + return io.object() == subject; + } +} diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/cfs/CheckCastReduction.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/cfs/CheckCastReduction.java Mon Apr 28 11:18:15 2014 +0200 @@ -0,0 +1,337 @@ +/* + * 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.phases.common.cfs; + +import com.oracle.graal.api.meta.*; +import com.oracle.graal.nodes.*; +import com.oracle.graal.nodes.calc.IsNullNode; +import com.oracle.graal.nodes.java.*; +import com.oracle.graal.compiler.common.type.ObjectStamp; +import com.oracle.graal.compiler.common.type.StampFactory; +import com.oracle.graal.nodes.type.StampTool; +import com.oracle.graal.phases.tiers.PhaseContext; + +import static com.oracle.graal.api.meta.DeoptimizationAction.InvalidateReprofile; +import static com.oracle.graal.api.meta.DeoptimizationReason.*; +import static com.oracle.graal.nodes.extended.BranchProbabilityNode.NOT_FREQUENT_PROBABILITY; + +/** + *

+ * This class implements control-flow sensitive reductions for + * {@link com.oracle.graal.nodes.java.CheckCastNode}. + *

+ * + * @see #visitCheckCastNode(com.oracle.graal.nodes.java.CheckCastNode) + * */ +public abstract class CheckCastReduction extends GuardingPiReduction { + + public CheckCastReduction(FixedNode start, State initialState, PhaseContext context) { + super(start, initialState, context); + } + + /** + *

+ * This phase is able to refine the types of reference-values at use sites provided a + * {@link com.oracle.graal.nodes.extended.GuardingNode GuardingNode} is available witnessing + * that fact. + *

+ * + *

+ * This method turns non-redundant {@link com.oracle.graal.nodes.java.CheckCastNode}s into + * {@link com.oracle.graal.nodes.GuardingPiNode}s. Once such lowering has been performed (during + * run N of this phase) follow-up runs attempt to further simplify the resulting node, see + * {@link EquationalReasoner#downcastedGuardingPiNode(com.oracle.graal.nodes.GuardingPiNode, Witness)} + * and {@link #visitGuardingPiNode(com.oracle.graal.nodes.GuardingPiNode)} + *

+ * + *

+ * Precondition: the inputs (ie, object) hasn't been deverbosified yet. + *

+ * */ + protected final void visitCheckCastNode(CheckCastNode checkCast) { + + /* + * checkCast.object() hasn't been deverbosified yet. + */ + + if (!FlowUtil.hasLegalObjectStamp(checkCast)) { + // This situation is exercised by test Class_cast01 + return; + } + + final ValueNode subject = checkCast.object(); + final ResolvedJavaType toType = checkCast.type(); + ObjectStamp subjectStamp = (ObjectStamp) subject.stamp(); + ResolvedJavaType subjectType = subjectStamp.type(); + + // --------- checkCast deemed redundant by subject-stamp alone --------- + // --------- in particular due to stamp informing always null ---------- + boolean isRedundantPerStamp = StampTool.isObjectAlwaysNull(subject) || (subjectType != null && toType.isAssignableFrom(subjectType)); + if (isRedundantPerStamp) { + metricCheckCastRemoved.increment(); + checkCast.replaceAtUsages(subject); + graph.removeFixed(checkCast); + return; + } + + assert !StampTool.isObjectAlwaysNull(subject) : "Null as per stamp subjects should have been handled above"; + + // --------- checkCast deemed unsatisfiable by subject-stamp alone --------- + if (state.knownNotToConform(subject, toType)) { + postponedDeopts.addDeoptBefore(checkCast, checkCast.isForStoreCheck() ? ArrayStoreException : ClassCastException); + state.impossiblePath(); + // let FixedGuardNode(false).simplify() prune the dead-code control-path + return; + } + + /* + * Remark: subject may be TypeProxyNode, GuardedValueNode, ProxyNode, GuardingPiNode, among + * others. + */ + + PiNode untrivialNull = reasoner.untrivialNull(subject); + if (untrivialNull != null) { + metricCheckCastRemoved.increment(); + checkCast.replaceAtUsages(untrivialNull); + graph.removeFixed(checkCast); + return; + } + + Witness w = state.typeInfo(subject); + + if (w == null) { + /* + * If there's no witness, attempting `downcasted(subject)` is futile. + */ + visitCheckCastNodeLackingWitness(checkCast); + return; + } + + visitCheckCastNodeWithWitness(checkCast); + + } + + /** + * Given that no witness is available for the {@link com.oracle.graal.nodes.java.CheckCastNode} + * 's subject there's no point in downcasting such subject, ie no + * {@link com.oracle.graal.nodes.PiNode} can be fabricated for the subject. + * + * @see #lowerCheckCastAnchorFriendlyWay(com.oracle.graal.nodes.java.CheckCastNode, + * com.oracle.graal.nodes.ValueNode) + * + * */ + private void visitCheckCastNodeLackingWitness(CheckCastNode checkCast) { + final ValueNode subject = checkCast.object(); + final ResolvedJavaType toType = checkCast.type(); + if (toType.isInterface()) { + return; + } + assert reasoner.downcasted(subject) == subject; + lowerCheckCastAnchorFriendlyWay(checkCast, subject); + } + + /** + * Porcelain method. + * + *

+ * Rather than tracking the CheckCastNode via {@link com.oracle.graal.phases.common.cfs.State + * State} (doing so woud add a special case because a + * {@link com.oracle.graal.nodes.java.CheckCastNode} isn't a + * {@link com.oracle.graal.nodes.extended.GuardingNode}) this method creates an anchor by + * lowering the CheckCastNode into a FixedGuardNode. Not the same way as done by + * {@link com.oracle.graal.nodes.java.CheckCastNode#lower(com.oracle.graal.nodes.spi.LoweringTool)} + * which lowers into a {@link com.oracle.graal.nodes.GuardingPiNode} (which is not a + * {@link com.oracle.graal.nodes.extended.GuardingNode}). + *

+ * + *

+ * With that, state tracking can proceed as usual. + *

+ * + * @see #visitCheckCastNode(com.oracle.graal.nodes.java.CheckCastNode) + * + * */ + public void lowerCheckCastAnchorFriendlyWay(CheckCastNode checkCast, ValueNode subject) { + ValueNode originalCheckCastObject = checkCast.object(); + + ObjectStamp subjectStamp = (ObjectStamp) subject.stamp(); + final ResolvedJavaType toType = checkCast.type(); + ObjectStamp resultStamp = (ObjectStamp) StampFactory.declared(toType); + JavaTypeProfile profile = checkCast.profile(); + + assert FlowUtil.isLegalObjectStamp(subjectStamp); + assert subjectStamp.type() == null || !toType.isAssignableFrom(subjectStamp.type()) : "No need to lower in an anchor-friendly way in the first place"; + + /* + * Depending on what is known about the subject: + * + * (a) definitely-non-null + * + * (b) null-not-seen-in-profiling + * + * (c) runtime-null-check-needed + * + * the condition (of the cast-guard to be emitted) and the stamp (of the PiNode to be + * emitted) are going to be different. Each of the three branches below deals with one of + * the cases above. + */ + LogicNode condition; + if (subjectStamp.nonNull()) { + /* + * (1 of 3) definitely-non-null + */ + // addWithoutUnique for the same reason as in CheckCastNode.lower() + condition = graph.addWithoutUnique(new InstanceOfNode(toType, subject, profile)); + reasoner.added.add(condition); + resultStamp = FlowUtil.asNonNullStamp(resultStamp); + // TODO fix in CheckCastNode.lower() + } else { + if (profile != null && profile.getNullSeen() == ProfilingInfo.TriState.FALSE) { + /* + * (2 of 3) null-not-seen-in-profiling + */ + IsNullNode isNN = graph.unique(new IsNullNode(subject)); + reasoner.added.add(isNN); + FixedGuardNode nullCheck = graph.add(new FixedGuardNode(isNN, UnreachedCode, InvalidateReprofile, true)); + graph.addBeforeFixed(checkCast, nullCheck); + // not calling wrapInPiNode() because we don't want to rememberSubstitution() + PiNode nonNullGuarded = graph.unique(new PiNode(subject, FlowUtil.asNonNullStamp(subjectStamp), nullCheck)); + reasoner.added.add(nonNullGuarded); + // addWithoutUnique for the same reason as in CheckCastNode.lower() + condition = graph.addWithoutUnique(new InstanceOfNode(toType, nonNullGuarded, profile)); + reasoner.added.add(condition); + resultStamp = FlowUtil.asNonNullStamp(resultStamp); + } else { + /* + * (3 of 3) runtime-null-check-needed + */ + // addWithoutUnique for the same reason as in CheckCastNode.lower() + InstanceOfNode typeTest = graph.addWithoutUnique(new InstanceOfNode(toType, subject, profile)); + reasoner.added.add(typeTest); + LogicNode nullTest = graph.unique(new IsNullNode(subject)); + reasoner.added.add(nullTest); + // TODO (ds) replace with probability of null-seen when available + final double shortCircuitProbability = NOT_FREQUENT_PROBABILITY; + condition = LogicNode.or(nullTest, typeTest, shortCircuitProbability); + reasoner.added.add(condition); + } + } + + /* + * Add a cast-guard (checking only what needs to be checked) and a PiNode (to be used in + * place of the CheckCastNode). + */ + FixedGuardNode castGuard = graph.add(new FixedGuardNode(condition, checkCast.isForStoreCheck() ? ArrayStoreException : ClassCastException, InvalidateReprofile)); + graph.addBeforeFixed(checkCast, castGuard); + + assert FlowUtil.isLegalObjectStamp(resultStamp); + Witness w = state.typeInfo(subject); + assert !isTypeOfWitnessBetter(w, resultStamp); + + if (!FlowUtil.lacksUsages(checkCast)) { + // not calling wrapInPiNode() because we don't want to rememberSubstitution() + PiNode checkedObject = graph.unique(new PiNode(subject, resultStamp, castGuard)); + reasoner.added.add(checkedObject); + assert !precisionLoss(originalCheckCastObject, checkedObject); + assert !precisionLoss(subject, checkedObject); + checkCast.replaceAtUsages(checkedObject); + } + + graph.removeFixed(checkCast); + + if (resultStamp.nonNull()) { + state.trackIO(subject, toType, castGuard); + } else { + state.trackCC(subject, toType, castGuard); + } + } + + /** + * Porcelain method. + * */ + public static boolean isTypeOfWitnessBetter(Witness w, ObjectStamp stamp) { + if (w == null) { + return false; + } + return FlowUtil.isMorePrecise(w.type(), stamp.type()); + } + + /** + * + * Please note in this method "subject" refers to the downcasted input to the checkCast. + * + * @see #visitCheckCastNode(com.oracle.graal.nodes.java.CheckCastNode) + * */ + private void visitCheckCastNodeWithWitness(CheckCastNode checkCast) { + + final ResolvedJavaType toType = checkCast.type(); + + ValueNode subject; + if (checkCast.object() instanceof CheckCastNode) { + subject = reasoner.downcasted(checkCast); + if (subject == checkCast) { + subject = reasoner.downcasted(checkCast.object()); + } + } else { + subject = reasoner.downcasted(checkCast.object()); + } + + ObjectStamp subjectStamp = (ObjectStamp) subject.stamp(); + ResolvedJavaType subjectType = subjectStamp.type(); + + // TODO move this check to downcasted() + assert !precisionLoss(checkCast.object(), subject); + + /* + * At this point, two sources of (partial) information: the witness and the stamp of + * subject. The latter might be more precise than the witness (eg, subject might be + * GuardedValueNode) + */ + + // --------- checkCast made redundant by downcasting its input --------- + if (subjectType != null && toType.isAssignableFrom(subjectType)) { + checkCast.replaceAtUsages(subject); + graph.removeFixed(checkCast); + return; + } + + /* + * At this point, `downcasted()` might or might not have delivered a more precise value. If + * more precise, it wasn't precise enough to conform to `toType`. Even so, for the + * `toType.isInterface()` case (dealt with below) we'll replace the checkCast's input with + * that value (its class-stamp being more precise than the original). + */ + + if (toType.isInterface()) { + boolean wasDowncasted = (subject != checkCast.object()); + if (wasDowncasted) { + FlowUtil.replaceInPlace(checkCast, checkCast.object(), subject); + } + return; + } + + lowerCheckCastAnchorFriendlyWay(checkCast, subject); + + } + +} diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/cfs/EquationalReasoner.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/cfs/EquationalReasoner.java Mon Apr 28 11:18:15 2014 +0200 @@ -0,0 +1,946 @@ +/* + * 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.phases.common.cfs; + +import com.oracle.graal.api.meta.ResolvedJavaType; +import com.oracle.graal.debug.Debug; +import com.oracle.graal.debug.DebugMetric; +import com.oracle.graal.graph.Node; +import com.oracle.graal.graph.NodeBitMap; +import com.oracle.graal.graph.spi.CanonicalizerTool; +import com.oracle.graal.nodes.*; +import com.oracle.graal.nodes.calc.FloatingNode; +import com.oracle.graal.nodes.calc.IsNullNode; +import com.oracle.graal.nodes.calc.ObjectEqualsNode; +import com.oracle.graal.nodes.extended.GuardedNode; +import com.oracle.graal.nodes.extended.GuardingNode; +import com.oracle.graal.nodes.java.CheckCastNode; +import com.oracle.graal.nodes.java.InstanceOfNode; +import com.oracle.graal.nodes.spi.ValueProxy; +import com.oracle.graal.compiler.common.type.IllegalStamp; +import com.oracle.graal.compiler.common.type.ObjectStamp; +import com.oracle.graal.compiler.common.type.StampFactory; +import com.oracle.graal.nodes.type.StampTool; +import com.oracle.graal.nodes.util.GraphUtil; + +import java.util.IdentityHashMap; +import java.util.Set; + +/** + *

+ * This class implements a simple partial evaluator that recursively reduces a given + * {@link com.oracle.graal.nodes.calc.FloatingNode} into a simpler one based on the current state. + * Such evaluator comes handy when visiting a {@link com.oracle.graal.nodes.FixedNode} N, just + * before updating the state for N. At the pre-state, an {@link EquationalReasoner + * EquationalReasoner} can be used to reduce N's inputs (actually only those inputs of Value and + * Condition {@link com.oracle.graal.graph.InputType InputType}). For an explanation of where it's + * warranted to replace "old input" with "reduced input", see the inline comments in method + * {@link EquationalReasoner#deverbosify(com.oracle.graal.graph.Node n) deverbosify(Node n)} + *

+ * + *

+ * The name {@link EquationalReasoner EquationalReasoner} was chosen because it conveys what it + * does. + *

+ */ +public final class EquationalReasoner { + + private static final DebugMetric metricInstanceOfRemoved = Debug.metric("InstanceOfRemoved"); + private static final DebugMetric metricNullCheckRemoved = Debug.metric("NullCheckRemoved"); + private static final DebugMetric metricObjectEqualsRemoved = Debug.metric("ObjectEqualsRemoved"); + private static final DebugMetric metricEquationalReasoning = Debug.metric("EquationalReasoning"); + private static final DebugMetric metricDowncasting = Debug.metric("Downcasting"); + + private final StructuredGraph graph; + private final CanonicalizerTool tool; + private final LogicConstantNode trueConstant; + private final LogicConstantNode falseConstant; + private final ConstantNode nullConstant; + + private State state; + private NodeBitMap visited; + + /** + * The reduction of a {@link com.oracle.graal.nodes.calc.FloatingNode} performed by + * {@link EquationalReasoner EquationalReasoner} may result in a FloatingNode being added to the + * graph. Those nodes aren't tracked in the {@link EquationalReasoner#visited visited} + * {@link com.oracle.graal.graph.NodeBitMap NodeBitMap} but in this set instead (those nodes are + * added after the {@link com.oracle.graal.graph.NodeBitMap} was obtained). + */ + final Set added = java.util.Collections.newSetFromMap(new IdentityHashMap()); + + /** + * The reduction of a FloatingNode performed by {@link EquationalReasoner EquationalReasoner} + * may result in a FloatingNode being added to the graph. Those nodes are tracked in this map, + * to avoid recomputing them. + * + * The substitutions tracked in this field become invalid as described in + * {@link #updateState(com.oracle.graal.phases.common.cfs.State) updateState(State)} + */ + private final IdentityHashMap substs = new IdentityHashMap<>(); + + public EquationalReasoner(StructuredGraph graph, CanonicalizerTool tool, LogicConstantNode trueConstant, LogicConstantNode falseConstant, ConstantNode nullConstant) { + this.graph = graph; + this.tool = tool; + this.trueConstant = trueConstant; + this.falseConstant = falseConstant; + this.nullConstant = nullConstant; + } + + /** + * {@link #added} grows during a run of + * {@link com.oracle.graal.phases.common.cfs.FlowSensitiveReductionPhase + * FlowSensitiveReductionPhase}, and doesn't survive across runs. + * */ + public void forceState(State s) { + state = s; + substs.clear(); + added.clear(); + visited = null; + versionNrAsofLastForce = s.versionNr; + } + + /** + *

+ * Gaining more precise type information about an SSA value doesn't "invalidate" as such any of + * the substitutions tracked in {@link EquationalReasoner#substs substs}, at least not in the + * sense of making the value tracked by one such entry "wrong". However, clearing the + * {@link EquationalReasoner#substs substs} is still justified because next time they are + * computed, the newly computed reduction could (in principle) be more effective (due to the + * more precise type information). + *

+ * + *

+ * Between clearings of cached substitutions, it is expected they get applied a number of times + * to justify the bookkeeping cost. + *

+ * + */ + public void updateState(State s) { + assert s != null; + if (state == null || state != s || state.versionNr != versionNrAsofLastForce) { + forceState(s); + } + } + + private int versionNrAsofLastForce = 0; + + /** + * Reduce the argument based on the state at the program point where the argument is consumed. + * For most FixedNodes, that's how their inputs can be reduced. Two exceptions: + *
    + *
  • + * the condition of a {@link com.oracle.graal.nodes.GuardingPiNode}, see + * {@link com.oracle.graal.phases.common.cfs.FlowSensitiveReduction#visitGuardingPiNode(com.oracle.graal.nodes.GuardingPiNode)} + *
  • + *
  • + * the condition of a {@link com.oracle.graal.nodes.FixedGuardNode}, see + * {@link com.oracle.graal.phases.common.cfs.FlowSensitiveReduction#visitFixedGuardNode(com.oracle.graal.nodes.FixedGuardNode)} + *
  • + * + *
+ * + * + *

+ * Part of the reduction work is delegated to baseCase-style reducers, whose contract explicitly + * requires them not to deverbosify the argument's inputs --- the decision is made based on the + * argument only (thus "base case"). Returning the unmodified argument is how a baseCase-style + * tells this method to fall to the default case (for a floating node only: walk into the + * argument's inputs, canonicalize followed by + * {@link #rememberSubstitution(com.oracle.graal.nodes.ValueNode, com.oracle.graal.nodes.ValueNode) + * rememberSubstitution()} if any input changed). + *

+ * + *

+ * This method must behave as a function (idempotent query method), ie refrain from mutating the + * state other than updating caches: + *

    + *
  • {@link EquationalReasoner#added EquationalReasoner#added},
  • + *
  • {@link EquationalReasoner#visited EquationalReasoner#visited} and
  • + *
  • the cache updated via + * {@link EquationalReasoner#rememberSubstitution(com.oracle.graal.nodes.ValueNode, com.oracle.graal.nodes.ValueNode) + * EquationalReasoner#rememberSubstitution(ValueNode, FloatingNode)}.
  • + *
+ *

+ * + *

+ * In turn, baseCase-style reducers are even more constrained: besides behaving as functions, + * their contract prevents them from updating any caches (basically because they already grab + * the answer from caches, if the answer isn't there they should just return their unmodified + * argument). + *

+ * + *

+ * This method returns: + *

    + *
  • + * the original argument, in case no reduction possible.
  • + *
  • + * a {@link com.oracle.graal.nodes.ValueNode ValueNode} different from the argument, in case the + * conditions for a reduction were met. The node being returned might be already in the graph. + * In any case it's canonicalized already, the caller need not perform that again.
  • + *
  • + * the unmodified argument, in case no reduction was made. Otherwise, a maximally reduced + * {@link com.oracle.graal.nodes.ValueNode}.
  • + *
+ *

+ * + * @see com.oracle.graal.phases.common.cfs.FlowSensitiveReduction#deverbosifyInputsInPlace(com.oracle.graal.nodes.ValueNode) + * + * @see com.oracle.graal.phases.common.cfs.BaseReduction.Tool + * + */ + public Node deverbosify(final Node n) { + + // -------------------------------------------------------------------- + // cases that don't initiate any call-chain that may enter this method + // -------------------------------------------------------------------- + + if (n == null) { + return null; + } + assert !(n instanceof GuardNode) : "This phase not yet ready to run during MidTier"; + if (!(n instanceof ValueNode)) { + return n; + } + ValueNode v = (ValueNode) n; + if (v.stamp() instanceof IllegalStamp) { + return v; + } + if (FlowUtil.isLiteralNode(v)) { + return v; + } + ValueNode result = substs.get(v); + if (result != null) { + // picked cached substitution + return result; + } + if ((visited != null && visited.contains(n)) || added.contains(v)) { + return v; + } + + // -------------------------------------------------------------------- + // stack overflow prevention via added, visited + // -------------------------------------------------------------------- + + if (visited == null) { + visited = graph.createNodeBitMap(); + } + visited.mark(n); + + /* + * Past this point, if we ever want `n` to be deverbosified, it must be looked-up by one of + * the cases above. One sure way to achieve that is with `rememberSubstitution(old, new)` + */ + if (v instanceof ValueProxy) { + return downcasted(v); + } + + if (n instanceof FloatingNode) { + /* + * `deverbosifyFloatingNode()` will drill down over floating inputs, when that not + * possible anymore it resorts to calling `downcasted()`. Thus it's ok to take the + * `deverbosifyFloatingNode()` route first, as no downcasting opportunity will be + * missed. + */ + return deverbosifyFloatingNode((FloatingNode) n); + } + + if (FlowUtil.hasLegalObjectStamp(v)) { + return downcasted(v); + } + + return n; + } + + /** + * This method: + * + *
    + *
  • + * Recurses only over floating inputs to attempt reductions, leave anything else as is.
  • + *
  • + * Performs copy-on-write aka lazy-DAG-copying as described in source comments, in-line.
  • + *
  • + * Usage: must be called only from {@link #deverbosify(com.oracle.graal.graph.Node) + * deverbosify(Node)}.
  • + *
+ * */ + public Node deverbosifyFloatingNode(final FloatingNode n) { + + assert n != null : "Should have been caught in deverbosify()"; + assert !(n instanceof ValueProxy) : "Should have been caught in deverbosify()"; + assert !FlowUtil.isLiteralNode(n) : "Should have been caught in deverbosify()"; + + if (n instanceof PhiNode) { + /* + * Each input to a PhiNode should be deverbosified with the state applicable to the path + * providing such input, as done in visitAbstractEndNode() + */ + return n; + } + + final FloatingNode f = baseCaseFloating(n); + if (f != n) { + return f; + } + + FloatingNode changed = null; + for (ValueNode i : FlowUtil.distinctValueAndConditionInputs(f)) { + /* + * Although deverbosify() is invoked below, it's only for floating inputs. That way, the + * state can't be used to make invalid conclusions. + */ + Node j = (i instanceof FloatingNode) ? deverbosify(i) : i; + if (i != j) { + assert j != f; + if (changed == null) { + changed = (FloatingNode) f.copyWithInputs(); + added.add(changed); + // copyWithInputs() implies graph.unique(changed) + assert changed.isAlive(); + assert FlowUtil.lacksUsages(changed); + } + /* + * Note: we don't trade i for j at each usage of i (doing so would change meaning) + * but only at those usages consumed by `changed`. In turn, `changed` won't replace + * `n` at arbitrary usages, but only where such substitution is valid as per the + * state holding there. In practice, this means the buck stops at the "root" + * FixedNode on whose inputs deverbosify() is invoked for the first time, via + * deverbosifyInputsInPlace(). + */ + FlowUtil.replaceInPlace(changed, i, j); + } + } + if (changed == null) { + assert visited.contains(f) || added.contains(f); + if (FlowUtil.hasLegalObjectStamp(f)) { + /* + * No input has changed doesn't imply there's no witness to refine the + * floating-object value. + */ + ValueNode d = downcasted(f); + return d; + } else { + return f; + } + } + FlowUtil.inferStampAndCheck(changed); + added.add(changed); + ValueNode canon = (ValueNode) changed.canonical(tool); + // might be already in `added`, no problem adding it again. + added.add(canon); + rememberSubstitution(f, canon); + return canon; + } + + /** + * In case of doubt (on whether a reduction actually triggered) it's always ok to invoke " + * rememberSubstitution(f, downcasted(f))": this method records a map entry only if + * pre-image and image differ. + * + * @return the image of the substitution (ie, the second argument) unmodified. + * */ + private M rememberSubstitution(ValueNode from, M to) { + assert from != null && to != null; + if (from == to) { + return to; + } + // we don't track literals because they map to themselves + if (FlowUtil.isLiteralNode(from)) { + assert from == to; + return to; + } + /* + * It's ok for different keys (which were not unique in the graph after all) to map to the + * same value. However any given key can't map to different values. + */ + ValueNode image = substs.get(from); + if (image != null) { + assert image == to; + return to; + } + substs.put(from, to); + return to; + } + + /** + * The contract for this baseCase-style method is covered in + * {@link EquationalReasoner#deverbosify(com.oracle.graal.graph.Node) + * EquationalReasoner#deverbosify()} + * + * @return a {@link com.oracle.graal.nodes.calc.FloatingNode} different from the argument, in + * case a reduction was made. The node being returned might be already in the graph. In + * any case it's canonicalized already, the caller need not perform that again. In case + * no reduction was made, this method returns the unmodified argument. + */ + private FloatingNode baseCaseFloating(final FloatingNode f) { + if (f instanceof LogicNode) { + FloatingNode result = baseCaseLogicNode((LogicNode) f); + return rememberSubstitution(f, result); + } + return f; + } + + /** + *

+ * Reduce the argument based on the state at the program point for it (ie, based on + * "valid facts" only, without relying on any floating-guard-assumption). + *

+ * + *

+ * The inputs of the argument aren't traversed into, for that + * {@link EquationalReasoner#deverbosify(com.oracle.graal.graph.Node) + * EquationalReasoner#deverbosify()} should be used instead. + *

+ *

+ * This method must behave as a function (idempotent query method): it should refrain from + * changing the state, as well as from updating caches (other than DebugMetric-s). + *

+ * + * @return a {@link com.oracle.graal.nodes.LogicNode} different from the argument, in case a + * reduction was made. The node being returned might be already in the graph. In any + * case it's canonicalized already, the caller need not perform that again. In case no + * reduction was made, this method returns the unmodified argument. + * + */ + public FloatingNode baseCaseLogicNode(LogicNode condition) { + assert condition != null; + if (condition instanceof LogicConstantNode) { + return condition; + } else if (state.trueFacts.containsKey(condition)) { + metricEquationalReasoning.increment(); + return trueConstant; + } else if (state.falseFacts.containsKey(condition)) { + metricEquationalReasoning.increment(); + return falseConstant; + } else { + if (condition instanceof InstanceOfNode) { + return baseCaseInstanceOfNode((InstanceOfNode) condition); + } else if (condition instanceof IsNullNode) { + return baseCaseIsNullNode((IsNullNode) condition); + } else if (condition instanceof ObjectEqualsNode) { + return baseCaseObjectEqualsNode((ObjectEqualsNode) condition); + } + } + return condition; + } + + /** + * Actually the same result delivered by this method could be obtained by just letting + * {@link EquationalReasoner#deverbosify(com.oracle.graal.graph.Node) + * EquationalReasoner#deverbosify()} handle the argument in the default case for floating nodes + * (ie, deverbosify inputs followed by canonicalize). However it's done here for metrics + * purposes. + * + * @return a {@link com.oracle.graal.nodes.LogicConstantNode}, in case a reduction was made; + * otherwise the unmodified argument. + * + */ + private LogicNode baseCaseInstanceOfNode(InstanceOfNode instanceOf) { + ValueNode scrutinee = GraphUtil.unproxify(instanceOf.object()); + if (!FlowUtil.hasLegalObjectStamp(scrutinee)) { + return instanceOf; + } + if (state.isNull(scrutinee)) { + metricInstanceOfRemoved.increment(); + return falseConstant; + } else if (state.isNonNull(scrutinee) && state.knownToConform(scrutinee, instanceOf.type())) { + metricInstanceOfRemoved.increment(); + return trueConstant; + } + return instanceOf; + } + + /** + * @return a {@link com.oracle.graal.nodes.LogicConstantNode}, in case a reduction was + * performed; otherwise the unmodified argument. + * + */ + private FloatingNode baseCaseIsNullNode(IsNullNode isNull) { + ValueNode object = isNull.object(); + if (!FlowUtil.hasLegalObjectStamp(object)) { + return isNull; + } + ValueNode scrutinee = GraphUtil.unproxify(isNull.object()); + GuardingNode evidence = untrivialNullAnchor(scrutinee); + if (evidence != null) { + metricNullCheckRemoved.increment(); + return trueConstant; + } else if (state.isNonNull(scrutinee)) { + metricNullCheckRemoved.increment(); + return falseConstant; + } + return isNull; + } + + /** + * @return a {@link com.oracle.graal.nodes.LogicConstantNode}, in case a reduction was made; + * otherwise the unmodified argument. + */ + private LogicNode baseCaseObjectEqualsNode(ObjectEqualsNode equals) { + if (!FlowUtil.hasLegalObjectStamp(equals.x()) || !FlowUtil.hasLegalObjectStamp(equals.y())) { + return equals; + } + ValueNode x = GraphUtil.unproxify(equals.x()); + ValueNode y = GraphUtil.unproxify(equals.y()); + if (state.isNull(x) && state.isNonNull(y) || state.isNonNull(x) && state.isNull(y)) { + metricObjectEqualsRemoved.increment(); + return falseConstant; + } else if (state.isNull(x) && state.isNull(y)) { + metricObjectEqualsRemoved.increment(); + return trueConstant; + } + return equals; + } + + /** + * It's always ok to use "downcasted(object)" instead of " object" + * because this method re-wraps the argument in a {@link com.oracle.graal.nodes.PiNode} only if + * the new stamp is strictly more refined than the original. + * + *

+ * This method does not + * {@link #rememberSubstitution(com.oracle.graal.nodes.ValueNode, com.oracle.graal.nodes.ValueNode)} + * . + *

+ * + * @return One of: + *
    + *
  • a {@link com.oracle.graal.nodes.PiNode} with more precise stamp than the input if + * the state warrants such downcasting
  • + *
  • a {@link com.oracle.graal.nodes.java.CheckCastNode CheckCastNode} for the same + * scrutinee in question
  • + *
  • the unmodified argument otherwise.
  • + *
+ */ + ValueNode downcasted(final ValueNode object) { + + // ------------------------------------------------- + // actions based only on the stamp of the input node + // ------------------------------------------------- + + if (!FlowUtil.hasLegalObjectStamp(object)) { + return object; + } + if (FlowUtil.isLiteralNode(object)) { + return object; + } + if (StampTool.isObjectAlwaysNull(object.stamp())) { + return untrivialNull(object); + } + + // ------------------------------------------ + // actions based on the stamp and the witness + // ------------------------------------------ + + ValueNode scrutinee = GraphUtil.unproxify(object); + + PiNode untrivialNull = untrivialNull(scrutinee); + if (untrivialNull != null) { + return untrivialNull; + } + + Witness w = state.typeInfo(scrutinee); + if (w == null) { + // no additional hints being tracked for the scrutinee + return object; + } + + assert !w.clueless(); + + ObjectStamp inputStamp = (ObjectStamp) object.stamp(); + ObjectStamp witnessStamp = w.asStamp(); + if (inputStamp.equals(witnessStamp) || !FlowUtil.isMorePrecise(witnessStamp, inputStamp)) { + // the witness offers no additional precision over current one + fixupTypeProfileStamp(object); + return object; + } + + assert !FlowUtil.isMorePrecise(inputStamp.type(), w.type()); + + ValueNode result; + if (object instanceof ValueProxy) { + result = downcastedValueProxy((ValueProxy) object, w); + } else { + result = downcastedUtil(object, w); + } + + return result; + } + + /** + * TODO TypeProfileProxyNode.inferStamp doesn't infer non-null from non-null payload + * + *

+ * And there's a bunch of asserts in + * {@link com.oracle.graal.phases.common.cfs.FlowSensitiveReductionPhase} that assert no + * type-precision gets lost. Thus the need to fix-up on our own, as done here. + *

+ * */ + private static void fixupTypeProfileStamp(ValueNode object) { + if (!(object instanceof TypeProfileProxyNode)) { + return; + } + TypeProfileProxyNode profile = (TypeProfileProxyNode) object; + ObjectStamp outgoinStamp = (ObjectStamp) profile.stamp(); + ObjectStamp payloadStamp = (ObjectStamp) profile.getObject().stamp(); + if (payloadStamp.nonNull() && !outgoinStamp.nonNull()) { + profile.setStamp(FlowUtil.asNonNullStamp(outgoinStamp)); + } + } + + /** + *

+ * Porcelain method. + *

+ * + *

+ * Utility to create, add to the graph, + * {@link EquationalReasoner#rememberSubstitution(com.oracle.graal.nodes.ValueNode, com.oracle.graal.nodes.ValueNode)} + * , and return a {@link com.oracle.graal.nodes.PiNode} that narrows into the given stamp, + * anchoring the payload. + *

+ * + *

+ * The resulting node might not have been in the graph already. + *

+ * */ + private PiNode wrapInPiNode(ValueNode payload, GuardingNode anchor, ObjectStamp newStamp, boolean remember) { + try (Debug.Scope s = Debug.scope("Downcast", payload)) { + assert payload != anchor : payload.graph().toString(); + metricDowncasting.increment(); + PiNode result = graph.unique(new PiNode(payload, newStamp, anchor.asNode())); + // we've possibly got a new node in the graph --- bookkeeping is in order. + added.add(result); + if (remember) { + rememberSubstitution(payload, result); + } + Debug.log("Downcasting from %s to %s", payload, result); + return result; + } catch (Throwable e) { + throw Debug.handle(e); + } + } + + /** + *

+ * If the argument is known null due to its stamp, there's no need to have an anchor for that + * fact and this method returns null. + *

+ * + *

+ * Otherwise, if an anchor is found it is returned, null otherwise. + *

+ */ + public GuardingNode untrivialNullAnchor(ValueNode object) { + assert FlowUtil.hasLegalObjectStamp(object); + if (StampTool.isObjectAlwaysNull(object)) { + return null; + } + return state.knownNull.get(GraphUtil.unproxify(object)); + } + + /** + * + * This method returns: + *
    + *
  • null, if the argument is known null due to its stamp. Otherwise,
  • + *
  • a PiNode wrapping the null constant and an anchor offering evidence as to why the + * argument is known null, if such anchor is available. Otherwise,
  • + *
  • null
  • + *
+ *

+ * This method does not + * {@link #rememberSubstitution(com.oracle.graal.nodes.ValueNode, com.oracle.graal.nodes.ValueNode)} + * . + *

+ */ + public PiNode untrivialNull(ValueNode object) { + assert FlowUtil.hasLegalObjectStamp(object); + GuardingNode anchor = untrivialNullAnchor(object); + if (anchor == null) { + return null; + } + if (object instanceof GuardedNode && StampTool.isObjectAlwaysNull(object.stamp())) { + return (PiNode) object; + } + // notice nullConstant is wrapped, not object + PiNode result = wrapInPiNode(nullConstant, anchor, (ObjectStamp) StampFactory.alwaysNull(), false); + return result; + } + + // @formatter:off + /** + *

ValueProxys can be classified along two dimensions, + * in addition to the fixed-floating dichotomy.

+ * + *

+ * First, we might be interested in separating those ValueProxys + * that are entitled to change (usually narrow) their stamp from those that aren't. + * In the first category are: + * PiNode, PiArrayNode, GuardingPiNode, + * CheckCastNode, UnsafeCastNode, and + * GuardedValueNode. + *

+ * + *

+ * A note on stamp-narrowing ValueProxys: + * our state abstraction tracks only the type refinements induced by CheckCastNode and GuardingPiNode + * (which are fixed nodes, unlike the other stamp-narrowing ValueProxys; + * the reason being that the state abstraction can be updated only at fixed nodes). + * As a result, the witness for a (PiNode, PiArrayNode, UnsafeCastNode, or GuardedValueNode) + * may be less precise than the proxy's stamp. We don't want to lose such precision, + * thus downcasted(proxy) == proxy in such cases. + *

+ * + *

+ * The second classification focuses on + * the additional information that travels with the proxy + * (in addition to its "payload", ie getOriginalValue(), and any narrowing-stamp). + * Such additional information boils down to: + * + * (a) type profile (TypeProfileProxyNode) + * (b) type profile (CheckCastNode) + * (c) anchor (GuardedValueNode) + * (d) anchor (PiNode) + * (e) anchor and array length (PiArrayNode) + * (f) optional anchor (UnsafeCastNode) + * (g) deopt-condition (GuardingPiNode) + * (h) LocationIdentity (MemoryProxyNOde) + * (i) control-flow dependency (FixedValueAnchorNode) + * (j) proxyPoint (ProxyNode -- think loops) + *

+ */ + // @formatter:on + private ValueNode downcastedValueProxy(ValueProxy proxy, Witness w) { + assert FlowUtil.hasLegalObjectStamp((ValueNode) proxy); + assert FlowUtil.hasLegalObjectStamp((proxy).getOriginalNode()); + assert GraphUtil.unproxify((ValueNode) proxy) == GraphUtil.unproxify(proxy.getOriginalNode()); + + assert GraphUtil.unproxify((ValueNode) proxy) == GraphUtil.unproxify((proxy).getOriginalNode()); + + if (proxy instanceof PiNode) { + return downcastedPiNodeOrPiArrayNode((PiNode) proxy, w); + } else if (proxy instanceof GuardingPiNode) { + return downcastedGuardingPiNode((GuardingPiNode) proxy, w); + } else if (proxy instanceof TypeProfileProxyNode) { + return downcastedTypeProfileProxyNode((TypeProfileProxyNode) proxy); + } else if (proxy instanceof CheckCastNode) { + return downcastedCheckCastNode((CheckCastNode) proxy, w); + } else if (proxy instanceof ProxyNode || proxy instanceof GuardedValueNode) { + // TODO scaladacapo return downcastedUtil((ValueNode) proxy, w); + return (ValueNode) proxy; + } + + assert false : "TODO case not yet handled"; + + // TODO complete the missing implementation for the cases not yet handled + + return ((ValueNode) proxy); + } + + /** + *

+ * Why would we want to downcast a GuardingPiNode? Is it even possible? Like, for example, a + * GuardingPiNode originating in the lowering of a CheckCastNode (carried out by + * {@link com.oracle.graal.phases.common.cfs.FlowSensitiveReduction#visitCheckCastNode(com.oracle.graal.nodes.java.CheckCastNode) + * visitCheckCastNode()}). + *

+ * + *

+ * It's both possible and desirable. Example: + * Number n = (Number) o; + * if (n instanceof Integer) { + * return n.intValue(); + * } + * + * + * The receiver of intValue() is a usage of a previous checkCast, for which the current witness + * provides a more refined type (and an anchor). In this case, the advantage of downcasting a + * GuardingPiNode is clear: devirtualizing the `intValue()` callsite. + *

+ * + * @see #downcastedValueProxy + * */ + public ValueNode downcastedGuardingPiNode(GuardingPiNode envelope, Witness w) { + assert envelope != w.guard().asNode() : "The stamp of " + envelope + " would lead to downcasting with that very same GuardingPiNode as guard."; + return downcastedUtil(envelope, w); + } + + /** + *

+ * This method accepts both {@link com.oracle.graal.nodes.PiNode} and + * {@link com.oracle.graal.nodes.PiArrayNode} argument. + *

+ * + *

+ * In case a witness reveals a strictly more precise type than the + * {@link com.oracle.graal.nodes.PiNode}'s stamp, this method wraps the argument in a new + * {@link com.oracle.graal.nodes.PiNode} with updated stamp, and returns it. + *

+ * + *

+ * A {@link com.oracle.graal.nodes.PiArrayNode} argument ends up wrapped in a + * {@link com.oracle.graal.nodes.PiNode}. Thus, the + * {@link com.oracle.graal.nodes.PiArrayNode#length} information doesn't get lost. + *

+ * + *

+ * Note: {@link com.oracle.graal.nodes.PiNode}'s semantics allow un-packing its payload as soon + * as it type conforms to that of the {@link com.oracle.graal.nodes.PiNode} (that's what + * {@link com.oracle.graal.nodes.PiNode#canonical(com.oracle.graal.graph.spi.CanonicalizerTool) + * PiNode.canonical()} does). Not clear the benefits of duplicating that logic here. + *

+ * + * @see #downcastedValueProxy + * */ + private ValueNode downcastedPiNodeOrPiArrayNode(PiNode envelope, Witness w) { + return downcastedUtil(envelope, w); + } + + /** + *

+ * In a case the payload of the {@link com.oracle.graal.nodes.TypeProfileProxyNode} can be + * downcasted, this method returns a copy-on-write version with the downcasted payload. + *

+ * + *

+ * Otherwise returns the unmodified argument. + *

+ * + * @see #downcastedValueProxy + * */ + private ValueNode downcastedTypeProfileProxyNode(TypeProfileProxyNode envelope) { + ValueNode payload = envelope.getOriginalNode(); + ValueNode d = downcasted(payload); + if (payload != d) { + TypeProfileProxyNode changed = (TypeProfileProxyNode) envelope.copyWithInputs(); + added.add(changed); + // copyWithInputs() implies graph.unique(changed) + FlowUtil.replaceInPlace(changed, payload, d); + FlowUtil.inferStampAndCheck(changed); + fixupTypeProfileStamp(changed); + /* + * It's not prudent to (1) obtain the canonical() of the (changed) TypeProfileProxyNode + * to (2) replace its usages; because we're potentially walking a DAG (after all, + * TypeProfileProxyNode is a floating-node). Those steps, which admittedly are needed, + * are better performed upon replacing in-place the inputs of a FixedNode, or during + * Canonicalize. + */ + return changed; + } + fixupTypeProfileStamp(envelope); + return envelope; + } + + /** + *

+ * Re-wrap the checkCast in a type-refining {@link com.oracle.graal.nodes.PiNode PiNode} only if + * the downcasted scrutinee does not conform to the checkCast's target-type. + *

+ * */ + private ValueNode downcastedCheckCastNode(CheckCastNode checkCast, Witness w) { + + final ResolvedJavaType toType = checkCast.type(); + + if (checkCast.object() instanceof CheckCastNode) { + ValueNode innerMost = checkCast; + while (innerMost instanceof CheckCastNode) { + innerMost = ((CheckCastNode) innerMost).object(); + } + ValueNode deepest = downcasted(innerMost); + ResolvedJavaType deepestType = ((ObjectStamp) deepest.stamp()).type(); + if ((deepestType != null && deepestType.equals(toType)) || FlowUtil.isMorePrecise(deepestType, toType)) { + assert !w.knowsBetterThan(deepest); + return deepest; + } + } + + ValueNode subject = downcasted(checkCast.object()); + ObjectStamp subjectStamp = (ObjectStamp) subject.stamp(); + ResolvedJavaType subjectType = subjectStamp.type(); + + if (subjectType != null && toType.isAssignableFrom(subjectType)) { + assert !w.knowsBetterThan(subject); + return subject; + } + + return downcastedUtil(checkCast, w); + } + + /** + *

+ * Porcelain method. + *

+ * + *

+ * This method wraps the argument in a new {@link com.oracle.graal.nodes.PiNode PiNode} (created + * to hold an updated stamp) provided the argument's stamp can be strictly refined, and returns + * it. + *

+ * */ + private ValueNode downcastedUtil(ValueNode subject, Witness w) { + + ObjectStamp originalStamp = (ObjectStamp) subject.stamp(); + ObjectStamp outgoingStamp = originalStamp; + + if (w.isNonNull() && !outgoingStamp.nonNull()) { + outgoingStamp = FlowUtil.asNonNullStamp(outgoingStamp); + } + if (FlowUtil.isMorePrecise(w.type(), outgoingStamp.type())) { + outgoingStamp = FlowUtil.asRefinedStamp(outgoingStamp, w.type()); + } + + if (outgoingStamp != originalStamp) { + assert FlowUtil.isMorePrecise(outgoingStamp, originalStamp); + + boolean isWitnessGuardAnAliasForScrutinee = false; + if (w.guard() instanceof GuardingPiNode || w.guard() instanceof PiNode) { + /* + * The guard offered by the witness canonicalizes into its subject (a possibly + * type-refined scrutinee) provided its subject conforms as per stamp. + */ + if (w.guard().asNode().stamp().equals(outgoingStamp)) { + isWitnessGuardAnAliasForScrutinee = true; + } + } + + ValueNode result; + if (isWitnessGuardAnAliasForScrutinee) { + result = w.guard().asNode(); + assert !w.knowsBetterThan(result); + return result; // TODO this works. explain why. + } else { + result = wrapInPiNode(subject, w.guard(), outgoingStamp, true); + assert !w.knowsBetterThan(result); + return result; + } + + } else { + assert !w.knowsBetterThan(subject); + return subject; + } + } + +} diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/cfs/FixedGuardReduction.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/cfs/FixedGuardReduction.java Mon Apr 28 11:18:15 2014 +0200 @@ -0,0 +1,218 @@ +/* + * 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.phases.common.cfs; + +import com.oracle.graal.nodes.*; +import com.oracle.graal.nodes.calc.IsNullNode; +import com.oracle.graal.nodes.extended.GuardingNode; +import com.oracle.graal.nodes.java.*; +import com.oracle.graal.phases.tiers.PhaseContext; + +/** + *

+ * This class implements control-flow sensitive reductions for + * {@link com.oracle.graal.nodes.FixedGuardNode}. + *

+ * + * @see #visitFixedGuardNode(com.oracle.graal.nodes.FixedGuardNode) + * */ +public abstract class FixedGuardReduction extends CheckCastReduction { + + public FixedGuardReduction(FixedNode start, State initialState, PhaseContext context) { + super(start, initialState, context); + } + + /** + * In case the condition is constant, + * {@link com.oracle.graal.nodes.FixedGuardNode#simplify(com.oracle.graal.graph.spi.SimplifierTool) + * FixedGuardNode#simplify(SimplifierTool)} will eventually remove the + * {@link com.oracle.graal.nodes.FixedGuardNode} ("always succeeds") or kill the code that + * should be killed ("always fails"). + * + *

+ * The only thing we do here is tracking as true fact (from this program point onwards) the + * condition of the {@link com.oracle.graal.nodes.FixedGuardNode FixedGuardNode}. + *

+ * + *

+ * Precondition: the condition hasn't been deverbosified yet. + *

+ */ + protected final void visitFixedGuardNode(FixedGuardNode f) { + + /* + * A FixedGuardNode with LogicConstantNode condition is left untouched. + */ + + if (f.condition() instanceof LogicConstantNode) { + if (FlowUtil.alwaysFails(f.isNegated(), f.condition())) { + state.impossiblePath(); + // let FixedGuardNode(false).simplify() prune the dead-code control-path + return; + } + assert FlowUtil.alwaysSucceeds(f.isNegated(), f.condition()); + return; + } + + /* + * Attempt to eliminate the current FixedGuardNode by using another GuardingNode already in + * scope and with equivalent condition. + */ + + GuardingNode existingGuard = f.isNegated() ? state.falseFacts.get(f.condition()) : state.trueFacts.get(f.condition()); + if (existingGuard != null) { + // assert existingGuard instanceof FixedGuardNode; + metricFixedGuardNodeRemoved.increment(); + f.replaceAtUsages(existingGuard.asNode()); + graph.removeFixed(f); + return; + } + + final LogicNode cond = f.condition(); + final boolean isTrue = !f.isNegated(); + + /* + * FixedGuardNode requires handling similar to that of GuardingPiNode, (ie the condition + * can't simply be deverbosified in place). A replacement anchor is needed, ie an anchor + * that amounts to the same combination of (negated, condition) for the FixedGuardNode at + * hand. + */ + + // TODO what about isDependencyTainted + + if (cond instanceof IsNullNode) { + final IsNullNode isNullNode = (IsNullNode) cond; + if (isTrue) { + // grab an anchor attesting nullness + final GuardingNode replacement = reasoner.untrivialNullAnchor(isNullNode.object()); + if (replacement != null) { + removeFixedGuardNode(f, replacement); + return; + } + if (state.isNonNull(isNullNode.object())) { + markFixedGuardNodeAlwaysFails(f); + return; + } + // can't produce evidence, fall-through to addFact + } else { + // grab an anchor attesting non-nullness + final Witness w = state.typeInfo(isNullNode.object()); + if (w != null && w.isNonNull()) { + removeFixedGuardNode(f, w.guard()); + return; + } + if (state.isNull(isNullNode.object())) { + markFixedGuardNodeAlwaysFails(f); + return; + } + // can't produce evidence, fall-through to addFact + } + } else if (cond instanceof InstanceOfNode) { + final InstanceOfNode iOf = (InstanceOfNode) cond; + final Witness w = state.typeInfo(iOf.object()); + if (isTrue) { + // grab an anchor attesting instanceof + if (w != null) { + if (w.isNonNull() && w.type() != null) { + if (iOf.type().isAssignableFrom(w.type())) { + removeFixedGuardNode(f, w.guard()); + return; + } + if (State.knownNotToConform(w.type(), iOf.type())) { + markFixedGuardNodeAlwaysFails(f); + return; + } + } + } + if (state.isNull(iOf.object())) { + markFixedGuardNodeAlwaysFails(f); + return; + } + // can't produce evidence, fall-through to addFact + } else { + // grab an anchor attesting not-instanceof + // (1 of 2) attempt determining nullness + final GuardingNode nullGuard = reasoner.untrivialNullAnchor(iOf.object()); + if (nullGuard != null) { + removeFixedGuardNode(f, nullGuard); + return; + } + // (2 of 2) attempt determining known-not-to-conform + if (w != null && !w.cluelessAboutType()) { + if (State.knownNotToConform(w.type(), iOf.type())) { + removeFixedGuardNode(f, w.guard()); + return; + } + } + // can't produce evidence, fall-through to addFact + } + } else if (isTrue && cond instanceof ShortCircuitOrNode) { + CastCheckExtractor cce = CastCheckExtractor.extract(cond); + if (cce != null && !State.isDependencyTainted(cce.subject, f)) { + // grab an anchor attesting check-cast + Witness w = state.typeInfo(cce.subject); + if (w != null && w.type() != null) { + if (cce.type.isAssignableFrom(w.type())) { + removeFixedGuardNode(f, w.guard()); + return; + } + if (State.knownNotToConform(w.type(), cce.type)) { + markFixedGuardNodeAlwaysFails(f); + return; + } + } + } + // can't produce evidence, fall-through to addFact + } + + state.addFact(isTrue, cond, f); + } + + /** + * Porcelain method. + * */ + private void markFixedGuardNodeAlwaysFails(FixedGuardNode f) { + metricFixedGuardNodeRemoved.increment(); + state.impossiblePath(); + f.setCondition(f.isNegated() ? trueConstant : falseConstant); + // `f.condition()` if unused will be removed in finished() + } + + /** + * Porcelain method. + * + *

+ * The `replacement` guard must be such that it implies the `old` guard. + *

+ * */ + private void removeFixedGuardNode(FixedGuardNode old, GuardingNode replacement) { + if (replacement == null) { + return; + } + metricFixedGuardNodeRemoved.increment(); + old.replaceAtUsages(replacement.asNode()); + graph.removeFixed(old); + // `old.condition()` if unused will be removed in finished() + } + +} diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/cfs/FlowSensitiveReduction.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/cfs/FlowSensitiveReduction.java Mon Apr 28 11:18:15 2014 +0200 @@ -0,0 +1,545 @@ +/* + * 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.phases.common.cfs; + +import com.oracle.graal.api.meta.*; +import com.oracle.graal.graph.Node; +import com.oracle.graal.nodes.*; +import com.oracle.graal.nodes.calc.FloatingNode; +import com.oracle.graal.nodes.extended.LoadHubNode; +import com.oracle.graal.nodes.extended.NullCheckNode; +import com.oracle.graal.nodes.java.*; +import com.oracle.graal.compiler.common.type.IllegalStamp; +import com.oracle.graal.nodes.type.StampTool; +import com.oracle.graal.nodes.util.GraphUtil; +import com.oracle.graal.phases.common.DeadCodeEliminationPhase; +import com.oracle.graal.phases.tiers.PhaseContext; + +import java.lang.reflect.Modifier; + +import static com.oracle.graal.api.meta.DeoptimizationReason.*; + +/** + *

+ * All control-flow-sensitive reductions follow the common pattern of + *

    + *
  • Recognizing properties of interest (ie, LogicNode-s) at control-flow splits, as well as upon + * check-casts and fixed-guards.
  • + *
  • Using the information thus tracked to simplify + *
      + *
    • side-effects free expressions, via + * {@link com.oracle.graal.phases.common.cfs.EquationalReasoner#deverbosify(com.oracle.graal.graph.Node)} + *
    • + *
    • control-flow, eg. by eliminating redundant fixed-guards and check-casts, ie which are known + * always to hold.
    • + *
    + *
  • + *
+ *

+ * + * @see com.oracle.graal.phases.common.cfs.CheckCastReduction + * @see com.oracle.graal.phases.common.cfs.GuardingPiReduction + * @see com.oracle.graal.phases.common.cfs.FixedGuardReduction + * + * */ +public class FlowSensitiveReduction extends FixedGuardReduction { + + public FlowSensitiveReduction(FixedNode start, State initialState, PhaseContext context) { + super(start, initialState, context); + } + + /** + *

+ * This method performs two kinds of cleanup: + *

    + *
  1. + * marking as unreachable certain code-paths, as described in + * {@link com.oracle.graal.phases.common.cfs.BaseReduction.PostponedDeopt}
  2. + *
  3. + * Removing nodes not in use that were added during this phase, as described next.
  4. + *
+ *

+ * + * + *

+ * Methods like + * {@link com.oracle.graal.phases.common.cfs.FlowUtil#replaceInPlace(com.oracle.graal.graph.Node, com.oracle.graal.graph.Node, com.oracle.graal.graph.Node)} + * may result in old inputs becoming disconnected from the graph. It's not advisable to + * {@link com.oracle.graal.nodes.util.GraphUtil#tryKillUnused(com.oracle.graal.graph.Node)} at + * that moment, because one of the inputs that might get killed is one of {@link #nullConstant}, + * {@link #falseConstant}, or {@link #trueConstant}; which thus could get killed too early, + * before another invocation of + * {@link com.oracle.graal.phases.common.cfs.EquationalReasoner#deverbosify(com.oracle.graal.graph.Node)} + * needs them. To recap, + * {@link com.oracle.graal.nodes.util.GraphUtil#tryKillUnused(com.oracle.graal.graph.Node)} also + * recursively visits the inputs of the its argument. + *

+ * + *

+ * This method goes over all of the nodes that deverbosification might have added, which are + * either: + *

    + *
  • + * {@link com.oracle.graal.nodes.calc.FloatingNode}, added by + * {@link com.oracle.graal.phases.common.cfs.EquationalReasoner#deverbosifyFloatingNode(com.oracle.graal.nodes.calc.FloatingNode)} + * ; or
  • + *
  • + * {@link com.oracle.graal.nodes.java.MethodCallTargetNode}, added by + * {@link #deverbosifyInputsCopyOnWrite(com.oracle.graal.nodes.java.MethodCallTargetNode)}
  • + *
+ * + * Checking if they aren't in use, proceeding to remove them in that case. + *

+ * + * */ + @Override + public void finished() { + if (!postponedDeopts.isEmpty()) { + for (PostponedDeopt postponed : postponedDeopts) { + postponed.doRewrite(falseConstant); + } + new DeadCodeEliminationPhase().apply(graph); + } + for (MethodCallTargetNode mcn : graph.getNodes().filter(MethodCallTargetNode.class)) { + if (mcn.isAlive() && FlowUtil.lacksUsages(mcn)) { + mcn.safeDelete(); + } + } + for (Node n : graph.getNodes().filter(FloatingNode.class)) { + GraphUtil.tryKillUnused(n); + } + assert !isAliveWithoutUsages(trueConstant); + assert !isAliveWithoutUsages(falseConstant); + assert !isAliveWithoutUsages(nullConstant); + } + + private static boolean isAliveWithoutUsages(FloatingNode node) { + return node.isAlive() && node.usages().isEmpty(); + } + + private void registerControlSplit(Node pred, BeginNode begin) { + assert pred != null && begin != null; + assert !state.isUnreachable; + + if (begin instanceof LoopExitNode) { + state.clear(); + } + + if (pred instanceof IfNode) { + registerIfNode((IfNode) pred, begin); + } else if (pred instanceof TypeSwitchNode) { + registerTypeSwitchNode((TypeSwitchNode) pred, begin); + } + } + + private void registerIfNode(IfNode ifNode, BeginNode begin) { + final boolean isThenBranch = (begin == ifNode.trueSuccessor()); + + if (ifNode.condition() instanceof LogicConstantNode) { + final LogicConstantNode constCond = (LogicConstantNode) ifNode.condition(); + if (isThenBranch != constCond.getValue()) { + state.impossiblePath(); + // let IfNode(constant) prune the dead-code control-path + } + } + + if (state.isUnreachable) { + if (!(ifNode.condition() instanceof LogicConstantNode)) { + // if condition constant, no need to add a Deopt node + postponedDeopts.addDeoptAfter(begin, UnreachedCode); + } + } else { + state.addFact(isThenBranch, ifNode.condition(), begin); + } + } + + /** + * TODO When tracking integer-stamps, the state at each successor of a TypeSwitchNode should + * track an integer-stamp for the LoadHubNode (meet over the constants leading to that + * successor). However, are LoadHubNode-s shared frequently enough? + * */ + private void registerTypeSwitchNode(TypeSwitchNode typeSwitch, BeginNode begin) { + if (typeSwitch.value() instanceof LoadHubNode) { + LoadHubNode loadHub = (LoadHubNode) typeSwitch.value(); + ResolvedJavaType type = null; + for (int i = 0; i < typeSwitch.keyCount(); i++) { + if (typeSwitch.keySuccessor(i) == begin) { + if (type == null) { + type = typeSwitch.typeAt(i); + } else { + type = FlowUtil.widen(type, typeSwitch.typeAt(i)); + } + } + } + if (type == null) { + // `begin` denotes the default case of the TypeSwitchNode + return; + } + // preferable would be trackExact, but not there yet + state.addNullness(false, loadHub.object(), begin); + if (state.knownNotToConform(loadHub.object(), type)) { + postponedDeopts.addDeoptAfter(begin, UnreachedCode); + state.impossiblePath(); + return; + } + if (type.isInterface()) { + state.trackNN(loadHub.object(), begin); + } else { + state.trackIO(loadHub.object(), type, begin); + } + } + } + + /** + * + *

+ * Reduce input nodes based on the state at the program point for the argument (ie, based on + * "valid facts" only, without relying on any floating-guard-assumption). + *

+ * + *

+ * For each (direct or indirect) child, a copy-on-write version is made in case any of its + * children changed, with the copy accommodating the updated children. If the parent was shared, + * copy-on-write prevents the updates from becoming visible to anyone but the invoker of this + * method. + *

+ * + *

+ * Please note the parent node is mutated upon any descendant changing. No copy-on-write is + * performed for the parent node itself. + *

+ * + *

+ * In more detail, for each direct {@link com.oracle.graal.nodes.ValueNode} input of the node at + * hand, + * + *

    + *
  1. + * Obtain a lazy-copied version (via spanning tree) of the DAG rooted at the input-usage in + * question. Lazy-copying is done by walking a spanning tree of the original DAG, stopping at + * non-FloatingNodes but transitively walking FloatingNodes and their inputs. Upon arriving at a + * (floating) node N, the state's facts are checked to determine whether a constant C can be + * used instead in the resulting lazy-copied DAG. A NodeBitMap is used to realize the spanning + * tree.
  2. + * + *
  3. + * Provided one or more N-to-C node replacements took place, the resulting lazy-copied DAG has a + * parent different from the original (ie different object identity) which indicates the + * (copied, updated) DAG should replace the original via replaceFirstInput(), and inferStamp() + * should be invoked to reflect the updated inputs.
  4. + * + *
+ *

+ * + * @return whether any reduction was performed on the inputs of the arguments. + * */ + public boolean deverbosifyInputsInPlace(ValueNode parent) { + boolean changed = false; + for (ValueNode i : FlowUtil.distinctValueAndConditionInputs(parent)) { + assert !(i instanceof GuardNode) : "ConditionalElim shouldn't run in MidTier"; + ValueNode j = (ValueNode) reasoner.deverbosify(i); + if (i != j) { + changed = true; + FlowUtil.replaceInPlace(parent, i, j); + } + } + if (changed) { + FlowUtil.inferStampAndCheck(parent); + } + return changed; + } + + /** + * Similar to {@link #deverbosifyInputsInPlace(com.oracle.graal.nodes.ValueNode)}, except that + * not the parent but a fresh clone is updated upon any of its children changing. + * + * @return the original parent if no updated took place, a copy-on-write version of it + * otherwise. + * + * */ + private MethodCallTargetNode deverbosifyInputsCopyOnWrite(MethodCallTargetNode parent) { + MethodCallTargetNode changed = null; + for (ValueNode i : FlowUtil.distinctValueAndConditionInputs(parent)) { + Node j = reasoner.deverbosify(i); + if (i != j) { + assert j != parent; + if (changed == null) { + changed = (MethodCallTargetNode) parent.copyWithInputs(); + reasoner.added.add(changed); + // copyWithInputs() implies graph.unique(changed) + assert changed.isAlive(); + assert FlowUtil.lacksUsages(changed); + } + FlowUtil.replaceInPlace(changed, i, j); + } + } + if (changed == null) { + return parent; + } + FlowUtil.inferStampAndCheck(changed); + /* + * No need to rememberSubstitution() because not called from deverbosify(). In detail, it's + * only deverbosify() that skips visited nodes (thus we'd better have recorded any + * substitutions we want for them). Not this case. + */ + return changed; + } + + /** + * Precondition: This method assumes that either: + * + *
    + *
  • the state has already stabilized (ie no more pending iterations in the "iterative" + * dataflow algorithm); or
  • + *
  • any rewritings made based on the state in its current form are conservative enough to be + * safe.
  • + *
+ * + *

+ * The overarching goal is to perform just enough rewriting to trigger other phases ( + * {@link com.oracle.graal.graph.spi.SimplifierTool SimplifierTool}, + * {@link com.oracle.graal.phases.common.DeadCodeEliminationPhase DeadCodeEliminationPhase}, + * etc) to perform the bulk of rewriting, thus lowering the maintenance burden. + *

+ * + */ + @Override + protected void node(FixedNode node) { + + assert node.isAlive(); + + /*------------------------------------------------------------------------------------- + * Step 1: Unreachable paths are still visited (PostOrderNodeIterator requires all ends + * of a merge to have been visited), but time is saved by neither updating the state nor + * rewriting anything while on an an unreachable path. + *------------------------------------------------------------------------------------- + */ + if (state.isUnreachable) { + return; + } + + /*------------------------------------------------------------------------------------- + * Step 2: For an AbstractBeginNode, determine whether this path is reachable, register + * any associated guards. + *------------------------------------------------------------------------------------- + */ + if (node instanceof BeginNode) { + BeginNode begin = (BeginNode) node; + Node pred = node.predecessor(); + + if (pred != null) { + registerControlSplit(pred, begin); + } + return; + } + + /*------------------------------------------------------------------------------------- + * Step 3: Check whether EquationalReasoner caches should be cleared upon state updates. + *------------------------------------------------------------------------------------- + */ + reasoner.updateState(state); + + /*------------------------------------------------------------------------------------- + * Step 4: Whatever special-case handling makes sense for the FixedNode at hand before + * its inputs are reduced. + *------------------------------------------------------------------------------------- + */ + + if (node instanceof AbstractEndNode) { + visitAbstractEndNode((AbstractEndNode) node); + return; + } else if (node instanceof Invoke) { + visitInvoke((Invoke) node); + return; + } else if (node instanceof CheckCastNode) { + // it's important not to call deverbosification for visitCheckCastNode() + visitCheckCastNode((CheckCastNode) node); + return; + } else if (node instanceof GuardingPiNode) { + visitGuardingPiNode((GuardingPiNode) node); + return; + } else if (node instanceof NullCheckNode) { + visitNullCheckNode((NullCheckNode) node); + return; + } else if (node instanceof FixedGuardNode) { + visitFixedGuardNode((FixedGuardNode) node); + return; + } else if (node instanceof ConditionAnchorNode) { + // ConditionAnchorNode shouldn't occur during HighTier + return; + } + + /*------------------------------------------------------------------------------------- + * Step 5: After special-case handling, we do our best for those FixedNode-s + * where the effort to reduce their inputs might pay off. + * + * Why is this useful? For example, by the time the AbstractBeginNode for an If-branch + * is visited (in general a ControlSplitNode), the If-condition will have gone already + * through simplification (and thus potentially have been reduced to a + * LogicConstantNode). + *------------------------------------------------------------------------------------- + */ + boolean paysOffToReduce = false; + if (node instanceof ControlSplitNode) { + // desire to simplify control flow + paysOffToReduce = true; + } else if (node instanceof ReturnNode) { + paysOffToReduce = true; + } else if (node instanceof AccessFieldNode || node instanceof AccessArrayNode) { + // desire to remove null-checks + paysOffToReduce = true; + } + + // TODO comb the remaining FixedWithNextNode subclasses, pick those with good changes of + // paying-off + + // TODO UnsafeLoadNode takes a condition + + if (paysOffToReduce) { + deverbosifyInputsInPlace(node); + } + + /*--------------------------------------------------------------------------------------- + * Step 6: Any additional special-case handling, this time after having inputs reduced. + * For example, leverage anchors provided by the FixedNode, to add facts to the factbase. + *--------------------------------------------------------------------------------------- + */ + + // TODO some nodes are GuardingNodes (eg, FixedAccessNode) we could use them to track state + // TODO others are additionally guarded (eg JavaReadNode), thus *their* guards could be + // simplified. + + } + + /** + * In case the scrutinee: + * + *
    + *
  • is known to be null, an unconditional deopt is added.
  • + *
  • is known to be non-null, the NullCheckNode is removed.
  • + *
+ * + *

+ * Precondition: the input (ie, object) hasn't been deverbosified yet. + *

+ * */ + private void visitNullCheckNode(NullCheckNode ncn) { + ValueNode object = ncn.getObject(); + if (state.isNull(object)) { + postponedDeopts.addDeoptBefore(ncn, NullCheckException); + state.impossiblePath(); + return; + } + if (state.isNonNull(object)) { + /* + * Redundant NullCheckNode. Unlike GuardingPiNode or FixedGuardNode, NullCheckNode-s + * aren't used as GuardingNode-s, thus in this case can be removed without further ado. + */ + assert FlowUtil.lacksUsages(ncn); + graph.removeFixed(ncn); + return; + } + // TODO ANCHOR NEEDED: state.trackNN(object, ncn); + } + + /** + * The {@link com.oracle.graal.nodes.AbstractEndNode} at the end of the current code path + * contributes values to {@link com.oracle.graal.nodes.PhiNode}s. Now is a good time to + * {@link EquationalReasoner#deverbosify(com.oracle.graal.graph.Node) + * EquationalReasoner#deverbosify} those values. + * + *

+ * Precondition: inputs haven't been deverbosified yet. + *

+ * */ + private void visitAbstractEndNode(AbstractEndNode endNode) { + MergeNode merge = endNode.merge(); + for (PhiNode phi : merge.phis()) { + if (phi instanceof ValuePhiNode && phi.getKind() == Kind.Object) { + assert phi.verify(); + int index = merge.phiPredecessorIndex(endNode); + ValueNode original = phi.valueAt(index); + ValueNode reduced = (ValueNode) reasoner.deverbosify(original); + if (reduced != original) { + phi.setValueAt(index, reduced); + // `original` if unused will be removed in finished() + } + } + } + } + + /** + * One or more arguments at `invoke` may have control-flow sensitive simplifications. In such + * case, a new {@link com.oracle.graal.nodes.java.MethodCallTargetNode MethodCallTargetNode} is + * prepared just for this callsite, consuming reduced arguments. This proves useful in + * connection with inlining, in order to specialize callees on the types of arguments other than + * the receiver (examples: multi-methods, the inlining problem, lambdas as arguments). + * + *

+ * Precondition: inputs haven't been deverbosified yet. + *

+ * */ + private void visitInvoke(Invoke invoke) { + if (invoke.asNode().stamp() instanceof IllegalStamp) { + return; // just to be safe + } + boolean isMethodCallTarget = invoke.callTarget() instanceof MethodCallTargetNode; + if (!isMethodCallTarget) { + return; + } + FlowUtil.replaceInPlace(invoke.asNode(), invoke.callTarget(), deverbosifyInputsCopyOnWrite((MethodCallTargetNode) invoke.callTarget())); + MethodCallTargetNode callTarget = (MethodCallTargetNode) invoke.callTarget(); + if (callTarget.invokeKind() != MethodCallTargetNode.InvokeKind.Interface && callTarget.invokeKind() != MethodCallTargetNode.InvokeKind.Virtual) { + return; + } + ValueNode receiver = callTarget.receiver(); + if (receiver == null) { + return; + } + if (!FlowUtil.hasLegalObjectStamp(receiver)) { + return; + } + Witness w = state.typeInfo(receiver); + ResolvedJavaType type; + ResolvedJavaType stampType = StampTool.typeOrNull(receiver); + if (w == null || w.cluelessAboutType()) { + // can't improve on stamp but wil try to devirtualize anyway + type = stampType; + } else { + type = FlowUtil.tighten(w.type(), stampType); + } + if (type == null) { + return; + } + ResolvedJavaMethod method = type.resolveMethod(callTarget.targetMethod()); + if (method == null) { + return; + } + if (method.canBeStaticallyBound() || Modifier.isFinal(type.getModifiers())) { + metricMethodResolved.increment(); + callTarget.setInvokeKind(MethodCallTargetNode.InvokeKind.Special); + callTarget.setTargetMethod(method); + } + } + +} diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/cfs/FlowSensitiveReductionPhase.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/cfs/FlowSensitiveReductionPhase.java Mon Apr 28 11:18:15 2014 +0200 @@ -0,0 +1,52 @@ +/* + * 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.phases.common.cfs; + +import com.oracle.graal.api.meta.*; +import com.oracle.graal.debug.*; +import com.oracle.graal.nodes.*; +import com.oracle.graal.phases.*; +import com.oracle.graal.phases.tiers.PhaseContext; + +public class FlowSensitiveReductionPhase extends BasePhase { + + private final MetaAccessProvider metaAccess; + + public MetaAccessProvider getMetaAccess() { + return metaAccess; + } + + public FlowSensitiveReductionPhase(MetaAccessProvider metaAccess) { + this.metaAccess = metaAccess; + } + + @Override + protected final void run(StructuredGraph graph, PhaseContext context) { + try (Debug.Scope s = Debug.scope("FlowSensitiveReduction")) { + new FlowSensitiveReduction(graph.start(), new State(), context).apply(); + } catch (Throwable e) { + throw Debug.handle(e); + } + } + +} \ No newline at end of file diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/cfs/FlowUtil.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/cfs/FlowUtil.java Mon Apr 28 11:18:15 2014 +0200 @@ -0,0 +1,317 @@ +/* + * 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.phases.common.cfs; + +import com.oracle.graal.api.meta.ResolvedJavaType; +import com.oracle.graal.debug.Debug; +import com.oracle.graal.debug.DebugConfig; +import com.oracle.graal.debug.DebugConfigScope; +import com.oracle.graal.debug.internal.DebugScope; +import com.oracle.graal.graph.InputType; +import com.oracle.graal.graph.Node; +import com.oracle.graal.graph.NodeClass; +import com.oracle.graal.nodes.*; +import com.oracle.graal.compiler.common.type.ObjectStamp; +import com.oracle.graal.compiler.common.type.Stamp; +import com.oracle.graal.compiler.common.type.StampFactory; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; + +public class FlowUtil { + + private FlowUtil() { + // no instances of this class + } + + public static boolean lacksUsages(Node n) { + return n.recordsUsages() && n.usages().isEmpty(); + } + + public static ResolvedJavaType widen(ResolvedJavaType a, ResolvedJavaType b) { + if (a == null || b == null) { + return null; + } else if (a.equals(b)) { + return a; + } else { + return a.findLeastCommonAncestor(b); + } + } + + /** + * @return whether the first argument is strictly more precise than the second. + * */ + public static boolean isMorePrecise(ResolvedJavaType a, ResolvedJavaType b) { + if (a == null) { + return false; + } + if (b == null) { + return true; + } + assert !a.isPrimitive(); + assert !b.isPrimitive(); + if (a.equals(b)) { + return false; + } + if (b.isInterface()) { + return b.isAssignableFrom(a); + } + if (a.isInterface()) { + return b.isInterface() && b.isAssignableFrom(a); + } + return b.isAssignableFrom(a); + } + + public static ResolvedJavaType tighten(ResolvedJavaType a, ResolvedJavaType b) { + if (a == null) { + assert b == null || !b.isPrimitive(); + return b; + } + if (b == null) { + assert !a.isPrimitive(); + return a; + } + assert !a.isPrimitive(); + assert !b.isPrimitive(); + if (a.equals(b)) { + return a; + } + if (isMorePrecise(a, b)) { + return a; + } else if (isMorePrecise(b, a)) { + return b; + } else { + /* + * Not comparable, two cases: + * + * Example 1: 'a' standing for j.l.Number and 'b' for j.l.String We return null for lack + * of a value representing NullType, the right answer. Same goes when both arguments are + * non-comparable interfaces. + * + * Example 2: 'a' standing for sun/nio/ch/DirectBuffer (an interface) and b for + * java/nio/Buffer (an abstract class). The class always takes precedence. + */ + if (a.isInterface()) { + return b.isInterface() ? null : b; + } + if (b.isInterface()) { + return a.isInterface() ? null : a; + } + return null; // a and b aren't comparable, can't tighten() them + } + } + + /** + * + * There are "illegal" stamps that are not of type IllegalStamp. + * + * For example, there may be an IntegerStamp with upperBound < lowerBound that returns + * !isLegal() but we still know it's an integer and thus not of type IllegalStamp. + * + * An IllegalStamp should never happen. In contrast, !isLegal() values could happen due to dead + * code not yet removed, or upon some non-sideeffecting instructions floating out of a dead + * branch. + * */ + public static boolean isLegalObjectStamp(Stamp s) { + return isObjectStamp(s) && s.isLegal(); + } + + public static boolean hasLegalObjectStamp(ValueNode v) { + return isLegalObjectStamp(v.stamp()); + } + + public static boolean isObjectStamp(Stamp stamp) { + return stamp instanceof ObjectStamp; + } + + public static void inferStampAndCheck(ValueNode n) { + n.inferStamp(); + if (n.stamp() instanceof ObjectStamp) { + ObjectStamp objectStamp = (ObjectStamp) n.stamp(); + assert !objectStamp.isExactType() || objectStamp.type() != null; + } + } + + /** + * Compares the arguments along three dimensions (nullness, exactness, and type). For the first + * argument to be more precise than the second, it may not score lower in any dimension and must + * score higher in at least one dimension. + * + * When comparing types s and t, sameness counts as 0; while being more precise is awarded with + * a score of 1. In all other cases (non-comparable, or supertype) the score is -1. + * + * @return whether the first argument is strictly more precise than the second. + * */ + public static boolean isMorePrecise(ObjectStamp a, ObjectStamp b) { + int d0 = MINUS(a.alwaysNull(), b.alwaysNull()); + if (d0 == -1) { + return false; + } + int d1 = MINUS(a.nonNull(), b.nonNull()); + if (d1 == -1) { + return false; + } + int d2 = MINUS(a.isExactType(), b.isExactType()); + if (d2 == -1) { + return false; + } + int d3; + ResolvedJavaType ta = a.type(); + ResolvedJavaType tb = b.type(); + if (ta == null) { + d3 = (tb == null) ? 0 : -1; + } else if (tb == null) { + d3 = 1; + } else if (isMorePrecise(ta, tb)) { + d3 = 1; + } else if (ta.equals(tb)) { + d3 = 0; + } else { + d3 = -1; + } + if (d3 == -1) { + return false; + } + int maxScore = Math.max(Math.max(d0, d1), Math.max(d2, d3)); + return maxScore > 0; + } + + private static int MINUS(boolean a, boolean b) { + int aa = a ? 1 : 0; + int bb = b ? 1 : 0; + return aa - bb; + } + + public static LogicConstantNode asLogicConstantNode(LogicNode cond) { + return (cond instanceof LogicConstantNode) ? (LogicConstantNode) cond : null; + } + + public static boolean isLiteralNode(ValueNode f) { + return f instanceof ConstantNode || f instanceof LogicConstantNode; + } + + public static boolean isConstantTrue(LogicNode cond) { + LogicConstantNode c = asLogicConstantNode(cond); + return (c != null) && c.getValue(); + } + + public static boolean isConstantFalse(LogicNode cond) { + LogicConstantNode c = asLogicConstantNode(cond); + return (c != null) && !c.getValue(); + } + + public static boolean alwaysFails(boolean isNegated, LogicNode cond) { + LogicConstantNode c = asLogicConstantNode(cond); + return (c != null) && (c.getValue() == isNegated); + } + + public static boolean alwaysSucceeds(boolean isNegated, LogicNode cond) { + LogicConstantNode c = asLogicConstantNode(cond); + return (c != null) && (c.getValue() != isNegated); + } + + /** + * Returns (preserving order) the ValueNodes without duplicates found among the argument's + * direct inputs. + * */ + @SuppressWarnings("unchecked") + public static List distinctValueAndConditionInputs(Node n) { + ArrayList result = null; + NodeClass.NodeClassIterator iter = n.inputs().iterator(); + while (iter.hasNext()) { + NodeClass.Position pos = iter.nextPosition(); + InputType inputType = pos.getInputType(n); + boolean isReducibleInput = (inputType == InputType.Value || inputType == InputType.Condition); + if (isReducibleInput) { + ValueNode i = (ValueNode) pos.get(n); + if (!isLiteralNode(i)) { + if (result == null) { + result = new ArrayList<>(); + } + if (!result.contains(i)) { + result.add(i); + } + } + } + } + return result == null ? Collections.EMPTY_LIST : result; + } + + public static ObjectStamp asNonNullStamp(ObjectStamp stamp) { + ObjectStamp result = (ObjectStamp) stamp.join(StampFactory.objectNonNull()); + assert result.isLegal(); + return result; + } + + public static ObjectStamp asRefinedStamp(ObjectStamp stamp, ResolvedJavaType joinType) { + assert !joinType.isInterface(); + ObjectStamp result = (ObjectStamp) stamp.join(StampFactory.declared(joinType)); + assert result.isLegal(); + return result; + } + + /** + * Start situation: the parent node has oldInput among its (direct) inputs. After + * this method has run, all such occurrences have been replaced with newInput. In + * case that makes oldInput disconnected, it is removed from the graph. + * */ + public static void replaceInPlace(Node parent, Node oldInput, Node newInput) { + assert parent != null; + assert parent.inputs().contains(oldInput); + if (oldInput == newInput) { + return; + } + assert oldInput != null && newInput != null; + assert !isLiteralNode((ValueNode) oldInput); + do { + parent.replaceFirstInput(oldInput, newInput); + } while (parent.inputs().contains(oldInput)); + // `oldInput` if unused wil be removed in finished() + } + + public static StructuredGraph visualize(StructuredGraph graph, String title) { + DebugConfig debugConfig = DebugScope.getConfig(); + DebugConfig fixedConfig = Debug.fixedConfig(false, true, false, false, debugConfig.dumpHandlers(), debugConfig.output()); + try (DebugConfigScope s = Debug.setConfig(fixedConfig)) { + Debug.dump(graph, title); + + return graph; + } + } + + public static final String ANSI_RESET = "\u001B[0m"; + public static final String ANSI_BLACK = "\u001B[30m"; + public static final String ANSI_RED = "\u001B[31m"; + public static final String ANSI_GREEN = "\u001B[32m"; + public static final String ANSI_YELLOW = "\u001B[33m"; + public static final String ANSI_BLUE = "\u001B[34m"; + public static final String ANSI_PURPLE = "\u001B[35m"; + public static final String ANSI_CYAN = "\u001B[36m"; + public static final String ANSI_WHITE = "\u001B[37m"; + + public static void highlightInRed(String msg) { + System.out.println(ANSI_RED + msg + ANSI_RESET); + } + +} diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/cfs/GuardingPiReduction.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/cfs/GuardingPiReduction.java Mon Apr 28 11:18:15 2014 +0200 @@ -0,0 +1,373 @@ +/* + * 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.phases.common.cfs; + +import com.oracle.graal.api.meta.*; +import com.oracle.graal.debug.Debug; +import com.oracle.graal.nodes.*; +import com.oracle.graal.nodes.calc.IsNullNode; +import com.oracle.graal.nodes.extended.GuardingNode; +import com.oracle.graal.nodes.java.*; +import com.oracle.graal.compiler.common.type.ObjectStamp; +import com.oracle.graal.nodes.type.StampTool; +import com.oracle.graal.phases.tiers.PhaseContext; + +/** + *

+ * This class implements control-flow sensitive reductions for + * {@link com.oracle.graal.nodes.GuardingPiNode}. + *

+ * + * @see #visitGuardingPiNode(com.oracle.graal.nodes.GuardingPiNode) + * */ +public abstract class GuardingPiReduction extends BaseReduction { + + public GuardingPiReduction(FixedNode start, State initialState, PhaseContext context) { + super(start, initialState, context); + } + + /** + *

+ * By the time a {@link com.oracle.graal.nodes.GuardingPiNode GuardingPiNode} is visited, the + * available type refinements may allow reductions similar to those performed for + * {@link com.oracle.graal.phases.common.cfs.FlowSensitiveReduction#visitCheckCastNode(com.oracle.graal.nodes.java.CheckCastNode) + * CheckCastNode}. + *

+ * + *
    + *
  1. + * If the condition needs no reduction (ie, it's already a + * {@link com.oracle.graal.nodes.LogicConstantNode LogicConstantNode}), this method basically + * gives up (thus letting other phases take care of it).
  2. + *
  3. + * Otherwise, an attempt is made to find a {@link com.oracle.graal.nodes.extended.GuardingNode} + * that implies the combination of (negated, condition) of the + * {@link com.oracle.graal.nodes.GuardingPiNode} being visited. Details in + * {@link #tryRemoveGuardingPiNode(com.oracle.graal.nodes.GuardingPiNode)}. If found, the node + * can be removed.
  4. + *
  5. + * Otherwise, the node is lowered to a {@link com.oracle.graal.nodes.FixedGuardNode} and its + * usages replaced with {@link com.oracle.graal.nodes.PiNode}. Details in + * {@link #visitGuardingPiNode(com.oracle.graal.nodes.GuardingPiNode)}.
  6. + *
+ * + *

+ * Precondition: the condition hasn't been deverbosified yet. + *

+ * + * */ + protected final void visitGuardingPiNode(GuardingPiNode envelope) { + + if (!FlowUtil.hasLegalObjectStamp(envelope)) { + // this situation exercised by com.oracle.graal.jtt.optimize.NCE_FlowSensitive02 + return; + } + if (!FlowUtil.hasLegalObjectStamp(envelope.object())) { + return; + } + + /* + * (1 of 3) Cover the case of GuardingPiNode(LogicConstantNode, ...) + */ + + if (envelope.condition() instanceof LogicConstantNode) { + if (FlowUtil.alwaysFails(envelope.isNegated(), envelope.condition())) { + state.impossiblePath(); + // let GuardingPiNode(false).canonical() prune the dead-code control-path + return; + } + // if not always-fails and condition-constant, then it always-succeeds! + assert FlowUtil.alwaysSucceeds(envelope.isNegated(), envelope.condition()); + // let GuardingPiNode(true).canonical() replaceAtUsages + return; + } + + /* + * The trick used in visitFixedGuardNode to look up an equivalent GuardingNode for the + * combination of (negated, condition) at hand doesn't work for GuardingPiNode, because the + * condition showing up here (a ShortCircuitOrNode that can be detected by + * CastCheckExtractor) doesn't appear as key in trueFacts, falseFacts. Good thing we have + * CastCheckExtractor! + */ + + /* + * (2 of 3) Cover the case of the condition known-to-be-false or known-to-be-true, but not + * LogicConstantNode. + * + * If deverbosify(condition) == falseConstant, it would be safe to set: + * `envelope.setCondition(falseConstant)` (only the API won't allow). + * + * On the other hand, it's totally unsafe to do something like that for trueConstant. What + * we can do about that case is the province of `tryRemoveGuardingPiNode(envelope)` + */ + + if (tryRemoveGuardingPiNode(envelope)) { + return; + } + + /* + * Experience has shown that an attempt to eliminate the current GuardingPiNode by using a + * GuardingNode already in scope and with equivalent condition (grabbed from `trueFacts` + * resp. `falseFacts`) proves futile. Therefore we're not even attempting that here. + */ + + /* + * (3 of 3) Neither always-succeeds nor always-fails, ie we don't known. Converting to + * FixedGuardNode allows tracking the condition via a GuardingNode, thus potentially + * triggering simplifications down the road. + */ + FixedGuardNode fixedGuard = graph.add(new FixedGuardNode(envelope.condition(), envelope.getReason(), envelope.getAction(), envelope.isNegated())); + graph.addBeforeFixed(envelope, fixedGuard); + + if (!FlowUtil.lacksUsages(envelope)) { + // not calling wrapInPiNode() because we don't want to rememberSubstitution() + PiNode replacement = graph.unique(new PiNode(envelope.object(), envelope.stamp(), fixedGuard)); + reasoner.added.add(replacement); + // before removing the GuardingPiNode replace its usages + envelope.replaceAtUsages(replacement); + } + + graph.removeFixed(envelope); + + state.addFact(!fixedGuard.isNegated(), fixedGuard.condition(), fixedGuard); + + } + + /** + *

+ * Based on flow-sensitive knowledge, two pre-requisites have to be fulfilled in order to remove + * a {@link com.oracle.graal.nodes.GuardingPiNode}: + * + *

    + *
  • the condition must refer only to the payload of the + * {@link com.oracle.graal.nodes.GuardingPiNode}
  • + *
  • the condition must check properties about which the state tracks not only a true/false + * answer, but also an anchor witnessing that fact
  • + *
  • the condition may not check anything else beyond what's stated in the items above.
  • + *
+ *

+ * + *

+ * Provided a condition as above can be reduced to a constant (and an anchor obtained in the + * process), this method replaces all usages of the + * {@link com.oracle.graal.nodes.GuardingPiNode} (necessarily of + * {@link com.oracle.graal.graph.InputType#Value}) with a {@link com.oracle.graal.nodes.PiNode} + * that wraps the payload and the anchor in question. + *

+ * + *

+ * Precondition: the condition hasn't been deverbosified yet. + *

+ * + * @see #visitGuardingPiNode(com.oracle.graal.nodes.GuardingPiNode) + * + * */ + private boolean tryRemoveGuardingPiNode(GuardingPiNode envelope) { + + LogicNode cond = envelope.condition(); + ValueNode payload = envelope.object(); + + ObjectStamp outgoingStamp = (ObjectStamp) envelope.stamp(); + ObjectStamp payloadStamp = (ObjectStamp) payload.stamp(); + + if (isNullCheckOn(cond, payload)) { + if (envelope.isNegated()) { + /* + * GuardingPiNode succeeds if payload non-null + */ + if (!outgoingStamp.equals(FlowUtil.asNonNullStamp(payloadStamp))) { + warnAboutOutOfTheBlueGuardingPiNode(envelope); + } + return tryRemoveGuardingPiNodeNonNullCond(envelope); + } else { + /* + * GuardingPiNode succeeds if payload null + */ + ValueNode replacement = StampTool.isObjectAlwaysNull(payload) ? payload : reasoner.untrivialNull(payload); + if (replacement != null) { + // replacement == null means !isKnownNull(payload) + removeGuardingPiNode(envelope, replacement); + return true; + } + return false; + } + } else if (CastCheckExtractor.isInstanceOfCheckOn(cond, payload)) { + if (envelope.isNegated()) { + return false; + } + /* + * GuardingPiNode succeeds if payload instanceof + */ + InstanceOfNode io = (InstanceOfNode) cond; + assert io.type() != null; + Witness w = state.typeInfo(payload); + if (w != null && w.isNonNull() && isEqualOrMorePrecise(w.type(), io.type())) { + ValueNode d = reasoner.downcasted(payload); + removeGuardingPiNode(envelope, d); + return true; + } + return false; + } else if (cond instanceof ShortCircuitOrNode) { + if (envelope.isNegated()) { + return false; + } + CastCheckExtractor cce = CastCheckExtractor.extract(cond); + if (cce == null || cce.subject != payload) { + return false; + } + /* + * GuardingPiNode succeeds if payload check-casts toType + */ + return tryRemoveGuardingPiNodeCheckCastCond(envelope, cce.type); + } + + return false; + } + + /** + * Porcelain method. + * + * This method handles the case where the GuardingPiNode succeeds if payload known to be + * non-null. + * + * @see #tryRemoveGuardingPiNode(com.oracle.graal.nodes.GuardingPiNode) + * */ + private boolean tryRemoveGuardingPiNodeNonNullCond(GuardingPiNode envelope) { + + ValueNode payload = envelope.object(); + + if (state.isNull(payload)) { + // the GuardingPiNode fails always + postponedDeopts.addDeoptBefore(envelope, envelope.getReason()); + state.impossiblePath(); + return true; + } + + if (StampTool.isObjectNonNull(payload)) { + // payload needs no downcasting, it satisfies as-is the GuardingPiNode's condition. + if (precisionLoss(envelope, payload)) { + /* + * TODO The GuardingPiNode has an outgoing stamp whose narrowing goes beyond what + * the condition checks. That's suspicious. + */ + PiNode replacement = graph.unique(new PiNode(payload, envelope.stamp())); + reasoner.added.add(replacement); + removeGuardingPiNode(envelope, replacement); + return true; + } else { + removeGuardingPiNode(envelope, payload); + return true; + } + } + // if a non-null witness available, the GuardingPiNode can be removed + + Witness w = state.typeInfo(payload); + GuardingNode nonNullAnchor = (w != null && w.isNonNull()) ? w.guard() : null; + if (nonNullAnchor != null) { + PiNode replacement = graph.unique(new PiNode(payload, envelope.stamp(), nonNullAnchor.asNode())); + reasoner.added.add(replacement); + removeGuardingPiNode(envelope, replacement); + return true; + } + + /* + * TODO What about, nodes that always denote non-null values? (Even though their stamp + * forgot to make that clear) Candidates: ObjectGetClassNode, Parameter(0) on instance + */ + + return false; + } + + /** + * Porcelain method. + * + * This method handles the case where the GuardingPiNode succeeds if payload null or its actual + * type equal or subtype of `toType` + * + * @see #tryRemoveGuardingPiNode(com.oracle.graal.nodes.GuardingPiNode) + * + * */ + private boolean tryRemoveGuardingPiNodeCheckCastCond(GuardingPiNode envelope, ResolvedJavaType toType) { + assert toType != null; + ValueNode payload = envelope.object(); + + ObjectStamp outgoingStamp = (ObjectStamp) envelope.stamp(); + ObjectStamp payloadStamp = (ObjectStamp) payload.stamp(); + + if (!outgoingStamp.equals(FlowUtil.asRefinedStamp(payloadStamp, toType))) { + warnAboutOutOfTheBlueGuardingPiNode(envelope); + } + + ValueNode d = reasoner.downcasted(payload); + if (d == null) { + return false; + } + + if (StampTool.isObjectAlwaysNull(d)) { + removeGuardingPiNode(envelope, d); + return true; + } + ObjectStamp dStamp = (ObjectStamp) d.stamp(); + if (isEqualOrMorePrecise(dStamp.type(), toType)) { + removeGuardingPiNode(envelope, d); + return true; + } + return false; + } + + /* + * TODO There should be an assert in GuardingPiNode to detect that as soon as it happens + * (constructor, setStamp). + */ + private static void warnAboutOutOfTheBlueGuardingPiNode(GuardingPiNode envelope) { + Debug.log(String.format("GuardingPiNode has an outgoing stamp whose narrowing goes beyond what its condition checks: %s", envelope)); + } + + private static boolean isNullCheckOn(LogicNode cond, ValueNode subject) { + if (!(cond instanceof IsNullNode)) { + return false; + } + IsNullNode isNull = (IsNullNode) cond; + return isNull.object() == subject; + } + + /** + * Porcelain method. + * */ + private void removeGuardingPiNode(GuardingPiNode envelope, ValueNode replacement) { + assert !precisionLoss(envelope, replacement); + metricGuardingPiNodeRemoved.increment(); + envelope.replaceAtUsages(replacement); + assert FlowUtil.lacksUsages(envelope); + graph.removeFixed(envelope); + } + + public static boolean isEqualOrMorePrecise(ResolvedJavaType a, ResolvedJavaType b) { + return a.equals(b) || FlowUtil.isMorePrecise(a, b); + } + + public static boolean isEqualOrMorePrecise(ObjectStamp a, ObjectStamp b) { + return a.equals(b) || FlowUtil.isMorePrecise(a, b); + } + +} diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/cfs/Histogram.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/cfs/Histogram.java Mon Apr 28 11:18:15 2014 +0200 @@ -0,0 +1,70 @@ +/* + * 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.phases.common.cfs; + +import java.util.Map; +import java.util.TreeMap; + +public class Histogram extends TreeMap { + + private static final long serialVersionUID = 7188324319057387738L; + + private final String prefix; + + public Histogram(String prefix) { + this.prefix = prefix; + } + + public void tick(int bucket) { + Integer entry = get(bucket); + put(bucket, entry == null ? 1 : entry + 1); + } + + public void print() { + + // printing takes time, allow concurrent updates during printing + Histogram histogram = clone(); + + float casesTotal = 0; + for (int i : histogram.values()) { + casesTotal += i; + } + for (Map.Entry entry : histogram.entrySet()) { + int numCases = entry.getValue(); + int percentOut = (int) (numCases / casesTotal * 100); + String msg = prefix + String.format("%d iters in %4d cases (%2d %%)", entry.getKey(), numCases, percentOut); + if (entry.getKey() > 3) { + FlowUtil.highlightInRed(msg); + } else { + System.out.println(msg); + } + } + System.out.println(prefix + "--------------------------"); + } + + @Override + public Histogram clone() { + return (Histogram) super.clone(); + } + +} diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/cfs/IterativeFlowSensitiveReductionPhase.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/cfs/IterativeFlowSensitiveReductionPhase.java Mon Apr 28 11:18:15 2014 +0200 @@ -0,0 +1,90 @@ +/* + * 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.phases.common.cfs; + +import com.oracle.graal.api.code.*; +import com.oracle.graal.graph.*; +import com.oracle.graal.graph.spi.*; +import com.oracle.graal.nodes.*; +import com.oracle.graal.phases.*; +import com.oracle.graal.phases.common.CanonicalizerPhase; +import com.oracle.graal.phases.common.util.*; +import com.oracle.graal.phases.tiers.*; + +public class IterativeFlowSensitiveReductionPhase extends BasePhase { + + private static final int MAX_ITERATIONS = 256; + + private final CanonicalizerPhase canonicalizer; + + public IterativeFlowSensitiveReductionPhase(CanonicalizerPhase canonicalizer) { + this.canonicalizer = canonicalizer; + } + + public static class CountingListener extends HashSetNodeChangeListener { + + public int count; + + @Override + public void nodeChanged(Node node) { + super.nodeChanged(node); + } + + } + + // private Histogram histogram = new Histogram("FSR-"); + + @Override + protected void run(StructuredGraph graph, PhaseContext context) { + FlowSensitiveReductionPhase eliminate = new FlowSensitiveReductionPhase(context.getMetaAccess()); + CountingListener listener = new CountingListener(); + int count = 1; + while (true) { + listener.count = count; + graph.trackInputChange(listener); + graph.trackUsagesDroppedZero(listener); + eliminate.apply(graph, context); + graph.stopTrackingInputChange(); + graph.stopTrackingUsagesDroppedZero(); + if (listener.getChangedNodes().isEmpty()) { + // histogram.tick(count); + break; + } + for (Node node : graph.getNodes()) { + if (node instanceof Simplifiable) { + listener.getChangedNodes().add(node); + } + } + canonicalizer.applyIncremental(graph, context, listener.getChangedNodes()); + listener.getChangedNodes().clear(); + if (++count > MAX_ITERATIONS) { + // System.out.println("Bailing out IterativeFlowSensitiveReductionPhase for graph: " + // + graph); + // FlowUtil.visualize(graph, "Bailout"); + throw new BailoutException("Number of iterations in FlowSensitiveReductionPhase exceeds " + MAX_ITERATIONS); + } + } + // histogram.print(); + } + +} diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/cfs/State.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/cfs/State.java Mon Apr 28 11:18:15 2014 +0200 @@ -0,0 +1,813 @@ +/* + * 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.phases.common.cfs; + +import com.oracle.graal.api.meta.Kind; +import com.oracle.graal.api.meta.ResolvedJavaType; +import com.oracle.graal.debug.Debug; +import com.oracle.graal.debug.DebugMetric; +import com.oracle.graal.nodes.*; +import com.oracle.graal.nodes.calc.IsNullNode; +import com.oracle.graal.nodes.calc.ObjectEqualsNode; +import com.oracle.graal.nodes.extended.GuardedNode; +import com.oracle.graal.nodes.extended.GuardingNode; +import com.oracle.graal.nodes.java.InstanceOfNode; +import com.oracle.graal.nodes.spi.ValueProxy; +import com.oracle.graal.compiler.common.type.ObjectStamp; +import com.oracle.graal.nodes.type.StampTool; +import com.oracle.graal.nodes.util.GraphUtil; +import com.oracle.graal.phases.graph.MergeableState; + +import java.lang.reflect.Modifier; +import java.util.*; + +/** + * A State instance is mutated in place as each FixedNode is visited in a basic block of + * instructions. Basic block: starts with a {@link com.oracle.graal.nodes.BeginNode BeginNode}, ends + * at an {@link com.oracle.graal.nodes.EndNode EndNode} or + * {@link com.oracle.graal.nodes.ControlSinkNode ControlSinkNode} and lacks intervening control + * splits or merges. + */ +public final class State extends MergeableState implements Cloneable { + + private static final DebugMetric metricTypeRegistered = Debug.metric("TypeRegistered"); + private static final DebugMetric metricNullnessRegistered = Debug.metric("NullnessRegistered"); + private static final DebugMetric metricObjectEqualsRegistered = Debug.metric("ObjectEqualsRegistered"); + private static final DebugMetric metricImpossiblePathDetected = Debug.metric("ImpossiblePathDetected"); + + /** + *

+ * Each state update results in a higher {@link State#versionNr versionNr}. The + * {@link State#versionNr versionNr} of different State instances can't be meaningfully compared + * (ie, same {@link State#versionNr versionNr} just indicates they've gone through the same + * number of updates). In particular, the {@link State#versionNr versionNr} of a merged state + * doesn't guarantee any more than being different from those of the states being merged. + *

+ * + *

+ * Still, {@link State#versionNr versionNr} proves useful in two cases: + * + *

    + *
  • recording the {@link State#versionNr versionNr} right after {@link State State} cloning, + * allows finding out afterwards whether (a) both states have diverged, (b) just one of them, or + * (c) none of them.
  • + *
  • a {@link State State} may become {@link State#isUnreachable isUnreachable}. In such case, + * it may make a difference whether any updates were performed on the state from the time it was + * cloned. Those updates indicate information not available in the state is was cloned from. For + * the purposes of {@link FlowSensitiveReduction FlowSensitiveReduction} an unreachable state + * need not be merged with any other (because control-flow won't reach the merge point over the + * path of the unreachable state).
  • + *
+ *

+ * + * */ + int versionNr = 0; + + boolean isUnreachable = false; + + /** + * Getting here implies an opportunity was detected for dead-code-elimination. A counterpoint + * argument goes as follows: perhaps we don't get here that often, in which case the effort to + * detect an "impossible path" could be shaved off. + * + * @see com.oracle.graal.phases.common.cfs.BaseReduction.PostponedDeopt + * */ + void impossiblePath() { + isUnreachable = true; + metricImpossiblePathDetected.increment(); + } + + /** + *

+ * This map semantically tracks "facts" (ie, properties valid for the program-point the state + * refers to) as opposed to floating-guard-dependent properties. The + * {@link com.oracle.graal.nodes.extended.GuardingNode} being tracked comes handy at + * {@link com.oracle.graal.phases.common.cfs.FlowSensitiveReduction#visitFixedGuardNode(com.oracle.graal.nodes.FixedGuardNode)} + * . + *

+ * + *

+ * On a related note, {@link #typeRefinements} also captures information the way + * {@link #trueFacts} and {@link #falseFacts} do, including "witnessing" guards. Why not just + * standardize on one of them, and drop the other? Because the {@link #typeRefinements} eagerly + * aggregates information for easier querying afterwards, e.g. when producing a "downcasted" + * value (which involves building a {@link com.oracle.graal.nodes.PiNode}, see + * {@link EquationalReasoner#downcasted(com.oracle.graal.nodes.ValueNode) downcasted()} + *

+ * + * */ + private IdentityHashMap typeRefinements; + + IdentityHashMap knownNull; + IdentityHashMap trueFacts; + IdentityHashMap falseFacts; + + public State() { + this.typeRefinements = new IdentityHashMap<>(); + this.knownNull = new IdentityHashMap<>(); + this.trueFacts = new IdentityHashMap<>(); + this.falseFacts = new IdentityHashMap<>(); + } + + public State(State other) { + this.isUnreachable = other.isUnreachable; + this.versionNr = other.versionNr; + this.typeRefinements = new IdentityHashMap<>(); + for (Map.Entry entry : other.typeRefinements.entrySet()) { + this.typeRefinements.put(entry.getKey(), new Witness(entry.getValue())); + } + this.knownNull = new IdentityHashMap<>(other.knownNull); + this.trueFacts = new IdentityHashMap<>(other.trueFacts); + this.falseFacts = new IdentityHashMap<>(other.falseFacts); + } + + /** + * @return A new list containing only those states that are reachable. + * */ + private static ArrayList reachableStates(List states) { + ArrayList result = new ArrayList<>(states); + Iterator iter = result.iterator(); + while (iter.hasNext()) { + if (iter.next().isUnreachable) { + iter.remove(); + } + } + return result; + } + + private IdentityHashMap mergeKnownTypes(MergeNode merge, ArrayList withReachableStates) { + IdentityHashMap newKnownTypes = new IdentityHashMap<>(); + + for (Map.Entry entry : typeRefinements.entrySet()) { + ValueNode node = entry.getKey(); + Witness type = new Witness(entry.getValue()); + + for (State other : withReachableStates) { + Witness otherType = other.typeInfo(node); + if (otherType == null) { + type = null; + break; + } + type.merge(otherType, merge); + } + if (type != null && type.knowsBetterThan(node)) { + assert node == GraphUtil.unproxify(node); + newKnownTypes.put(node, type); + } + } + + return newKnownTypes; + } + + private IdentityHashMap mergeKnownNull(MergeNode merge, ArrayList withReachableStates) { + // newKnownNull starts empty + IdentityHashMap newKnownNull = new IdentityHashMap<>(); + for (Map.Entry entry : knownNull.entrySet()) { + ValueNode key = entry.getKey(); + GuardingNode newGN = entry.getValue(); + boolean missing = false; + + for (State other : withReachableStates) { + GuardingNode otherGuard = other.knownNull.get(key); + if (otherGuard == null) { + missing = true; + break; + } + if (otherGuard != newGN) { + newGN = merge; + } + } + if (!missing) { + newKnownNull.put(key, newGN); + } + } + return newKnownNull; + } + + /** + *

+ * This method handles phis, by adding to the resulting state any information that can be gained + * (about type-refinement and nullness) based on the data available at each of the incoming + * branches. + *

+ * + *

+ * In more detail, FlowSensitiveReduction#visitAbstractEndNode() has already + * deverbosified the phi-values contributed by each reachable branch. The paths that + * {@link com.oracle.graal.phases.common.cfs.FlowSensitiveReduction} determined to be + * unreachable will be eliminated by canonicalization and dead code elimination. For now they + * still exist, thus polluting the result of + * {@link com.oracle.graal.nodes.ValuePhiNode#inferPhiStamp()} but we are careful to skip them + * when merging type-witnesses and known-null maps. + *

+ */ + private void mergePhis(MergeNode merge, List withStates, IdentityHashMap newKnownPhiTypes, IdentityHashMap newKnownNullPhis) { + + if (merge instanceof LoopBeginNode) { + return; + } + + for (PhiNode phi : merge.phis()) { + assert phi == GraphUtil.unproxify(phi); + if (phi instanceof ValuePhiNode && phi.getKind() == Kind.Object) { + ArrayList reachingValues = new ArrayList<>(); + if (!isUnreachable) { + reachingValues.add(phi.valueAt(0)); + } + for (int i = 0; i < withStates.size(); i++) { + State otherState = withStates.get(i); + if (!otherState.isUnreachable) { + reachingValues.add(phi.valueAt(i + 1)); + } + } + assert !reachingValues.isEmpty(); + ObjectStamp phiStamp = (ObjectStamp) phi.stamp(); + ObjectStamp nonPollutedStamp = (ObjectStamp) StampTool.meet(reachingValues); + Witness w = new Witness(nonPollutedStamp, merge); + if (FlowUtil.isMorePrecise(w.type(), phiStamp.type())) { + // precision gain regarding type + newKnownPhiTypes.put(phi, w); + // confirm no precision loss regarding nullness + assert implies(phiStamp.nonNull(), w.isNonNull()); + } else if (w.isNonNull() && !phiStamp.nonNull()) { + // precision gain regarding nullness + newKnownPhiTypes.put(phi, w); + // confirm no precision loss regarding type + assert !FlowUtil.isMorePrecise(phiStamp.type(), w.type()); + } + if (nonPollutedStamp.alwaysNull()) { + newKnownNullPhis.put(phi, merge); + } + } + } + + } + + private static boolean implies(boolean a, boolean b) { + return !a || b; + } + + @Override + public boolean merge(MergeNode merge, List withStates) { + + ArrayList withReachableStates = reachableStates(withStates); + if (withReachableStates.isEmpty()) { + return true; + } + + for (State state : withReachableStates) { + versionNr = Math.max(versionNr, state.versionNr) + 1; + isUnreachable &= state.isUnreachable; + } + + if (isUnreachable) { + typeRefinements.clear(); + knownNull.clear(); + return true; + } + + // may also get updated in a moment, during processing of phi nodes. + IdentityHashMap newKnownTypes = mergeKnownTypes(merge, withReachableStates); + // may also get updated in a moment, during processing of phi nodes. + IdentityHashMap newKnownNull = mergeKnownNull(merge, withReachableStates); + mergePhis(merge, withStates, newKnownTypes, newKnownNull); + this.typeRefinements = newKnownTypes; + this.knownNull = newKnownNull; + + this.trueFacts = mergeTrueFacts(withReachableStates, merge); + this.falseFacts = mergeFalseFacts(withReachableStates, merge); + return true; + } + + private IdentityHashMap mergeTrueFacts(ArrayList withReachableStates, GuardingNode merge) { + IdentityHashMap newTrueConditions = new IdentityHashMap<>(); + for (Map.Entry entry : trueFacts.entrySet()) { + LogicNode check = entry.getKey(); + GuardingNode guard = entry.getValue(); + + for (State other : withReachableStates) { + GuardingNode otherGuard = other.trueFacts.get(check); + if (otherGuard == null) { + guard = null; + break; + } + if (otherGuard != guard) { + guard = merge; + } + } + if (guard != null) { + newTrueConditions.put(check, guard); + } + } + return newTrueConditions; + } + + private IdentityHashMap mergeFalseFacts(ArrayList withReachableStates, GuardingNode merge) { + IdentityHashMap newFalseConditions = new IdentityHashMap<>(); + for (Map.Entry entry : falseFacts.entrySet()) { + LogicNode check = entry.getKey(); + GuardingNode guard = entry.getValue(); + + for (State other : withReachableStates) { + GuardingNode otherGuard = other.falseFacts.get(check); + if (otherGuard == null) { + guard = null; + break; + } + if (otherGuard != guard) { + guard = merge; + } + } + if (guard != null) { + newFalseConditions.put(check, guard); + } + } + return newFalseConditions; + } + + /** + * @retun null if no type-witness available for the argument, the witness otherwise. + */ + public Witness typeInfo(ValueNode object) { + assert FlowUtil.hasLegalObjectStamp(object); + return typeRefinements.get(GraphUtil.unproxify(object)); + } + + /** + * @retun true iff the argument is known to stand for null. + */ + public boolean isNull(ValueNode object) { + assert FlowUtil.hasLegalObjectStamp(object); + return StampTool.isObjectAlwaysNull(object) || knownNull.containsKey(GraphUtil.unproxify(object)); + } + + /** + *

+ * It makes a difference calling {@link Witness#isNonNull()} as opposed to + * {@link State#isNonNull(com.oracle.graal.nodes.ValueNode)}. The former guarantees the witness + * provides a guard certifying non-nullness. The latter just tells us there exists some guard + * that certifies the property we asked about. + *

+ * + *

+ * TODO improvement: isKnownNonNull could be made smarter by noticing some nodes always denote a + * non-null value (eg, ObjectGetClassNode). Similarly for isKnownNull. Code that looks at the + * stamp as well as code that looks for a non-null-witness would benefit from also checking such + * extended isKnownNonNull. Alternatively, the stamp of those nodes should always have + * is-non-null set. + *

+ * + * @retun true iff the argument is known to stand for non-null. + */ + public boolean isNonNull(ValueNode object) { + assert FlowUtil.hasLegalObjectStamp(object); + if (StampTool.isObjectNonNull(object)) { + return true; + } + Witness w = typeInfo(object); + return w == null ? false : w.isNonNull(); + } + + /** + * @retun true iff the argument is known to stand for an object conforming to the given type. + */ + public boolean knownToConform(ValueNode object, ResolvedJavaType to) { + assert FlowUtil.hasLegalObjectStamp(object); + assert !to.isPrimitive(); + ResolvedJavaType stampType = StampTool.typeOrNull(object); + if (stampType != null && to.isAssignableFrom(stampType)) { + return true; + } + final ValueNode scrutinee = GraphUtil.unproxify(object); + if (isNull(scrutinee)) { + return true; + } + Witness w = typeInfo(scrutinee); + boolean witnessAnswer = w != null && w.type() != null && to.isAssignableFrom(w.type()); + if (witnessAnswer) { + return true; + } + return false; + } + + /** + * @retun true iff the argument is known to stand for an object that definitely does not conform + * to the given type. + */ + public boolean knownNotToConform(ValueNode object, ResolvedJavaType to) { + assert FlowUtil.hasLegalObjectStamp(object); + assert !to.isPrimitive(); + final ValueNode scrutinee = GraphUtil.unproxify(object); + if (isNull(scrutinee)) { + return false; + } + ResolvedJavaType stampType = StampTool.typeOrNull(object); + if (stampType != null && knownNotToConform(stampType, to)) { + return true; + } + Witness w = typeInfo(scrutinee); + boolean witnessAnswer = w != null && !w.cluelessAboutType() && knownNotToConform(w.type(), to); + if (witnessAnswer) { + return true; + } + return false; + } + + // @formatter:off + /** + * \ | | | | + * \ b| | | | + * a \ | | | | + * \|iface|final|non-f| + * -----+-----------------| + * iface| F | F | F | + * -----+-----------------| + * final| C | C | C | + * -----+-----------------| + * non-f| F | C | C | + * -----------------------+ + * + * where: + * F: false + * C: check + * iface: interface + * final: exact non-interface reference-type + * non-f: non-exact non-interface reference-type + * + * @retun true iff the first argument is known not to conform to the second argument. + */ + // @formatter:on + public static boolean knownNotToConform(ResolvedJavaType a, ResolvedJavaType b) { + assert !a.isPrimitive(); + assert !b.isPrimitive(); + if (b.isAssignableFrom(a)) { + return false; + } + if (a.isInterface()) { + return false; + } + boolean aFinal = Modifier.isFinal(a.getModifiers()); + if (b.isInterface() && !aFinal) { + return false; + } + if (a.isAssignableFrom(b)) { + return false; + } else { + return true; + } + } + + @Override + public State clone() { + return new State(this); + } + + /** + * Porcelain method. + */ + private Witness getOrElseAddTypeInfo(ValueNode object) { + ValueNode scrutinee = GraphUtil.unproxify(object); + Witness w = typeRefinements.get(scrutinee); + if (w == null) { + w = new Witness(); + typeRefinements.put(scrutinee, w); + } + return w; + } + + /** + *

+ * Updates this {@link State State} to account for an observation about the scrutinee being + * non-null. In case instanceof was observed, + * {@link #trackIO(com.oracle.graal.nodes.ValueNode, com.oracle.graal.api.meta.ResolvedJavaType, com.oracle.graal.nodes.extended.GuardingNode) + * trackIO(ResolvedJavaType, GuardingNode)} should be invoked instead. + *

+ * + *

+ * No check is made on whether a contradiction would be introduced into the factbase (in which + * case the state should be marked unreachable), the caller takes care of that. + *

+ * + * @return whether state was updated (iff the observation added any new information) + */ + public boolean trackNN(ValueNode object, GuardingNode anchor) { + if (isDependencyTainted(object, anchor)) { + return false; + } + ResolvedJavaType stampType = StampTool.typeOrNull(object); + if (stampType != null && !stampType.isInterface()) { + return trackIO(object, stampType, anchor); + } + Witness w = getOrElseAddTypeInfo(object); + if (w.trackNN(anchor)) { + versionNr++; + return true; + } + return false; + } + + /** + * Updates this {@link State State} to account for an observation about the scrutinee conforming + * to a type. In case instanceof was observed, + * {@link #trackIO(com.oracle.graal.nodes.ValueNode, com.oracle.graal.api.meta.ResolvedJavaType, com.oracle.graal.nodes.extended.GuardingNode) + * trackIO(ResolvedJavaType, GuardingNode)} should be invoked instead. + * + *

+ * No check is made on whether a contradiction would be introduced into the factbase (in which + * case the state should be marked unreachable), the caller must take care of that. + *

+ * + * @return false iff the observed type is an interface, or doesn't provide any new information + * not already known. Ie, this method returns true iff the observation resulted in + * information gain. + */ + public boolean trackCC(ValueNode object, ResolvedJavaType observed, GuardingNode anchor) { + if (observed.isInterface()) { + return false; + } + if (isDependencyTainted(object, anchor)) { + return false; + } + Witness w = getOrElseAddTypeInfo(object); + if (w.trackCC(observed, anchor)) { + versionNr++; + metricTypeRegistered.increment(); + return true; + } + return false; + } + + /** + * Updates this {@link State State} to account for an observation about the non-null scrutinee + * conforming to a type. + * + *

+ * No check is made on whether a contradiction would be introduced into the factbase (in which + * case the state should be marked unreachable), the caller must take care of that. + *

+ * + * @return whether state was updated (iff the observation added any new information) + */ + public boolean trackIO(ValueNode object, ResolvedJavaType observed, GuardingNode anchor) { + assert !observed.isInterface() : "no infrastructure yet in State.Witness to support interfaces in general"; + if (isDependencyTainted(object, anchor)) { + return false; + } + Witness w = getOrElseAddTypeInfo(object); + if (w.trackIO(observed, anchor)) { + versionNr++; + metricTypeRegistered.increment(); + return true; + } + return false; + } + + /** + * This method increases {@link #versionNr} (thus potentially invalidating + * {@link EquationalReasoner EquationalReasoner}'s caches) only if the fact wasn't known + * already. + * + *

+ * No check is made on whether a contradiction would be introduced into the factbase (in which + * case the state should be marked unreachable), the caller must take care of that. + *

+ * + * */ + private void addFactPrimordial(LogicNode condition, IdentityHashMap to, GuardingNode anchor) { + assert condition != null; + if (!to.containsKey(condition)) { + versionNr++; + to.put(condition, anchor); + } + } + + /** + * Ideas for the future: + *
    + *
  • track inferred less-than edges from (accumulated) CompareNode-s
  • + *
  • track set-representative for equality classes determined by (chained) IntegerTestNode
  • + *
+ * + * */ + public void addFact(boolean isTrue, LogicNode condition, GuardingNode anchor) { + assert anchor != null; + assert !isUnreachable; + + if (condition instanceof LogicConstantNode) { + if (((LogicConstantNode) condition).getValue() != isTrue) { + impossiblePath(); + } + return; + } + + if (condition instanceof LogicNegationNode) { + addFact(!isTrue, ((LogicNegationNode) condition).getInput(), anchor); + } else if (condition instanceof ShortCircuitOrNode) { + /* + * We can register the conditions being or-ed as long as the anchor is a fixed node, + * because floating guards will be registered at a BeginNode but might be "valid" only + * later due to data flow dependencies. Therefore, registering both conditions of a + * ShortCircuitOrNode for a floating guard could lead to cycles in data flow, because + * the guard will be used as anchor for both conditions, and one condition could be + * depending on the other. + */ + if (isTrue) { + CastCheckExtractor cce = CastCheckExtractor.extract(condition); + if (cce == null || isDependencyTainted(cce.subject, anchor)) { + addFactPrimordial(condition, isTrue ? trueFacts : falseFacts, anchor); + } else { + trackCC(cce.subject, cce.type, anchor); + } + } else { + ShortCircuitOrNode disjunction = (ShortCircuitOrNode) condition; + addFact(disjunction.isXNegated(), disjunction.getX(), anchor); + // previous addFact might have resulted in impossiblePath() + if (isUnreachable) { + return; + } + addFact(disjunction.isYNegated(), disjunction.getY(), anchor); + } + } else if (condition instanceof InstanceOfNode) { + addFactInstanceOf(isTrue, (InstanceOfNode) condition, anchor); + } else if (condition instanceof IsNullNode) { + IsNullNode nullCheck = (IsNullNode) condition; + addNullness(isTrue, nullCheck.object(), anchor); + } else if (condition instanceof ObjectEqualsNode) { + addFactObjectEqualsNode(isTrue, (ObjectEqualsNode) condition, anchor); + } else { + addFactPrimordial(condition, isTrue ? trueFacts : falseFacts, anchor); + } + } + + /** + * An instanceof hint is tracked differently depending on whether it's an interface-test or not + * (because type-refinements currently lacks the ability to track interface types). + * + */ + private void addFactInstanceOf(boolean isTrue, InstanceOfNode instanceOf, GuardingNode anchor) { + ValueNode object = instanceOf.object(); + if (isTrue) { + if (knownNotToConform(object, instanceOf.type())) { + impossiblePath(); + return; + } + addNullness(false, object, anchor); + if (instanceOf.type().isInterface()) { + if (!knownToConform(object, instanceOf.type())) { + addFactPrimordial(instanceOf, trueFacts, anchor); + } + } else { + trackIO(object, instanceOf.type(), anchor); + } + } else { + if (knownToConform(object, instanceOf.type())) { + impossiblePath(); // TODO this used to be a bug + return; + } + if (instanceOf.type().isInterface()) { + if (!knownNotToConform(object, instanceOf.type())) { + addFactPrimordial(instanceOf, falseFacts, anchor); + } + } + } + } + + private void addFactObjectEqualsNode(boolean isTrue, ObjectEqualsNode equals, GuardingNode anchor) { + if (isDependencyTainted(equals.x(), anchor)) { + return; + } + if (isDependencyTainted(equals.y(), anchor)) { + return; + } + ValueNode x = GraphUtil.unproxify(equals.x()); + ValueNode y = GraphUtil.unproxify(equals.y()); + if (isTrue) { + if (isNull(x) && isNonNull(y)) { + impossiblePath(); + return; + } + if (isNonNull(x) && isNull(y)) { + impossiblePath(); + return; + } + if (isNull(x) || isNull(y)) { + metricObjectEqualsRegistered.increment(); + addNullness(true, equals.x(), anchor); + addNullness(true, equals.y(), anchor); + } else if (isNonNull(x) || isNonNull(y)) { + metricObjectEqualsRegistered.increment(); + addNullness(false, equals.x(), anchor); + addNullness(false, equals.y(), anchor); + } + Witness wx = typeInfo(x); + Witness wy = typeInfo(y); + if (wx == null && wy == null) { + return; + } else if (wx != null && wy != null) { + // tighten their type-hints, provided at least one available + // both witnesses may have seen == null, ie they may be NN witnesses + ResolvedJavaType best = FlowUtil.tighten(wx.type(), wy.type()); + if (best != null) { + assert !best.isInterface(); + // type tightening is enough, nullness already taken care of + trackCC(equals.x(), best, anchor); + trackCC(equals.y(), best, anchor); + } + } else if (wx == null) { + typeRefinements.put(x, new Witness(wy)); + } else if (wy == null) { + typeRefinements.put(y, new Witness(wx)); + } + } else { + if (isNull(x) && !isNonNull(y)) { + metricObjectEqualsRegistered.increment(); + addNullness(false, equals.y(), anchor); + } else if (!isNonNull(x) && isNull(y)) { + metricObjectEqualsRegistered.increment(); + addNullness(false, equals.x(), anchor); + } + } + } + + /** + * Adds information about the nullness of a value. If isNull is true then the value is known to + * be null, otherwise the value is known to be non-null. + */ + public void addNullness(boolean isNull, ValueNode value, GuardingNode anchor) { + if (isDependencyTainted(value, anchor)) { + return; + } + ValueNode original = GraphUtil.unproxify(value); + boolean wasNull = isNull(original); + boolean wasNonNull = isNonNull(original); + if (isNull) { + if (wasNonNull) { + impossiblePath(); + } else { + metricNullnessRegistered.increment(); + versionNr++; + knownNull.put(original, anchor); + } + } else { + if (wasNull) { + impossiblePath(); + } else { + metricNullnessRegistered.increment(); + trackNN(original, anchor); + } + } + } + + /** + * + * @return true iff `value` may lose dependency not covered by `anchor`. + * */ + public static boolean isDependencyTainted(ValueNode value, GuardingNode anchor) { + if (value instanceof ValueProxy) { + if (value instanceof GuardedNode) { + GuardedNode gn = (GuardedNode) value; + GuardingNode guardian = gn.getGuard(); + if (guardian != null) { + boolean isGuardedByFixed = guardian instanceof FixedNode; + if (!isGuardedByFixed) { + return true; + } + } + } + // if (value instanceof GuardingNode) { + // return true; + // } + ValueProxy proxy = (ValueProxy) value; + return isDependencyTainted(proxy.getOriginalNode(), anchor); + } + return false; + } + + public void clear() { + versionNr = 0; + isUnreachable = false; + typeRefinements.clear(); + knownNull.clear(); + } + +} diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/cfs/Witness.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/cfs/Witness.java Mon Apr 28 11:18:15 2014 +0200 @@ -0,0 +1,440 @@ +/* + * 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.phases.common.cfs; + +import com.oracle.graal.api.meta.ResolvedJavaType; +import com.oracle.graal.nodes.*; +import com.oracle.graal.nodes.extended.GuardingNode; +import com.oracle.graal.compiler.common.type.ObjectStamp; + +/** + *

+ * A witness progressively tracks more detailed properties about an object value (the scrutinee); + * the properties in question comprise whether the scrutinee has been observed: + * + *

    + *
  • as non-null,
  • + *
  • in a successful checkcast, or
  • + *
  • in a successful instanceof.
  • + *
+ *

+ * + *

+ * A witness is updated only when doing so increases the information content of the witness. For + * example, upon visiting a {@link com.oracle.graal.nodes.java.CheckCastNode CheckCastNode} the + * witness gets a chance to become updated. + *

+ * + *

+ * Therefore, at any given time, a witness represents the most detailed knowledge available so far + * about the scrutinee, which is the knowledge most relevant for upcoming program-points. + *

+ * + *

+ * The availability of witnesses about both non-nullness and checkcast (for a given scrutinee) + * promotes to an instanceof-style witness . The "levels" of knowledge a witness may exhibit are + * captured by {@link com.oracle.graal.phases.common.cfs.Witness.LEVEL}. For conciseness, the + * following query methods are available for a {@link com.oracle.graal.phases.common.cfs.Witness}: + *

    + *
  • {@link #atNonNull()}
  • + *
  • {@link #atCheckCast()}
  • + *
  • {@link #atInstanceOf()}
  • + *
+ *

+ * + *

+ * Only non-interface object types (ie, class and array types) are tracked. Small extensions are + * required to track interfaces, extensions that might be added after the current scheme proves + * itself. + *

+ * + *

+ * Some useful facts about the Statechart implemented by {@link Witness Witness}: + * + *

    + *
  • the start-state is "clueless"
  • + *
  • + * A self-transition via trackCC from whichever the current state is to itself, without information + * gain, is always possible. Just give {@link Object java.lang.Object} as observed type.
  • + *
+ *

+ * + */ +public class Witness implements Cloneable { + + private static enum LEVEL { + CLUELESS, + NN, + CC, + IO + } + + private boolean atNonNull() { + return level == LEVEL.NN; + } + + private boolean atCheckCast() { + return level == LEVEL.CC; + } + + private boolean atInstanceOf() { + return level == LEVEL.IO; + } + + private void transition(LEVEL to, GuardingNode newAnchor) { + this.level = to; + this.gn = newAnchor; + assert repOK(); + } + + public Witness() { + } + + public Witness(Witness other) { + level = other.level; + seen = other.seen; + gn = other.gn; + } + + /** + * Counterpart to {@link #asStamp()} + * */ + public Witness(ObjectStamp stamp, GuardingNode anchor) { + assert stamp.isLegal(); + assert anchor != null; + boolean isNonIface = (stamp.type() != null && !stamp.type().isInterface()); + if (stamp.nonNull()) { + if (isNonIface) { + seen = stamp.type(); + transition(LEVEL.IO, anchor); + } else { + seen = null; + transition(LEVEL.NN, anchor); + } + } else { + if (isNonIface) { + seen = stamp.type(); + transition(LEVEL.CC, anchor); + } else { + seen = null; + transition(LEVEL.CLUELESS, null); + assert clueless(); + } + } + assert repOK(); + } + + /** + * Type-witnesses aren't tracked for known-to-be-null. Therefore, although method + * {@link #isNonNull() isNonNull()} can be found in this class there's on purpose no companion + * isNull() . + */ + public boolean isNonNull() { + return atNonNull() || atInstanceOf(); + } + + /** + * The most precise type known so far about the scrutinee. (Please notice that nothing can be + * deduced about the non-nullness-status of the scrutinee from invoking this method alone). + */ + public ResolvedJavaType type() { + return seen; + } + + public ObjectStamp asStamp() { + boolean isKnownExact = (seen != null && seen.equals(seen.asExactType())); + return new ObjectStamp(seen, isKnownExact, isNonNull(), false); + } + + private LEVEL level = LEVEL.CLUELESS; + private ResolvedJavaType seen = null; + + /** + * Evidence (ie, a {@link com.oracle.graal.nodes.extended.GuardingNode}) attesting to the status + * reported by this witness. + * + * May be one of: + * + *
    + *
  • + * {@link com.oracle.graal.nodes.BeginNode BeginNode},
  • + *
  • + * {@link com.oracle.graal.nodes.LoopExitNode LoopExitNode},
  • + *
  • + * {@link com.oracle.graal.nodes.FixedGuardNode FixedGuardNode}
  • + *
  • {@link com.oracle.graal.nodes.MergeNode MergeNode}, resulting from merging two witnesses + * with different values for this anchor
  • + *
+ * + *

+ * An {@link com.oracle.graal.nodes.calc.ObjectEqualsNode ObjectEqualsNode} test results in the + * more-clueless of both scrutinees having its witness upgraded to that of the other (both + * scrutinees share the same {@link Witness Witness} instance from then on). For this reason, + * this field may also hold the anchors associated to an + * {@link com.oracle.graal.nodes.calc.ObjectEqualsNode ObjectEqualsNode} occurrence, ie nodes + * that can serve as {@link com.oracle.graal.nodes.extended.GuardingNode GuardingNode} for the + * purposes of building a {@link com.oracle.graal.nodes.PiNode PiNode}. + *

+ * + */ + private GuardingNode gn = null; + + /** + * Invariants of this class: + *
    + *
  • All fields holding null is ok, the hallmark of a {@link #clueless() clueless} witness. + * Another way for a witness to be clueless is by recording java.lang.Object as the + * seen type and nothing more.
  • + *
  • {@link #seen seen} may be null as long as the only hint being recorded is non-nullness
  • + *
  • A non-null value for {@link #seen seen} can't be tracked with NN, that combination + * amounts to IO and is tracked as such
  • + *
  • At most one of NN, CC, IO may be tracked at any given time
  • + *
  • A non-null CC or a non-null IO force {@link #seen seen} to be non-null
  • + *
  • {@link #seen seen} must be null or denote a non-interface reference type (ie, either a + * class-type or an array-type)
  • + *
+ */ + private boolean repOK() { + if (clueless()) { + assert level == LEVEL.CLUELESS; + return true; + } + if (level == LEVEL.NN) { + assert seen == null; + } + if (seen != null) { + assert !seen.isInterface(); + assert !seen.isPrimitive(); + } + boolean gnOK = gn instanceof BeginNode || gn instanceof LoopExitNode || gn instanceof MergeNode || gn instanceof FixedGuardNode; + assert gnOK; + return true; + } + + /** + * Helper method for readability in complex conditions. + */ + public boolean clueless() { + return cluelessAboutType() && cluelessAboutNonNullness(); + } + + /** + * Helper method for readability in complex conditions. + */ + public boolean cluelessAboutType() { + // TODO also clueless when `seen` is `java.lang.Object` + return seen == null; + } + + /** + * Helper method for readability in complex conditions. + */ + public boolean cluelessAboutNonNullness() { + return !atNonNull() && !atInstanceOf(); + } + + /** + * Whether this {@link Witness Witness} tracks information strictly more precise than that in + * the given {@link com.oracle.graal.compiler.common.type.ObjectStamp}. + */ + boolean knowsBetterThan(ObjectStamp other) { + return FlowUtil.isMorePrecise(asStamp(), other); + } + + /** + * Whether this {@link Witness Witness} tracks information strictly more precise than that in + * the {@link com.oracle.graal.compiler.common.type.ObjectStamp} of the given argument. + */ + boolean knowsBetterThan(ValueNode other) { + return knowsBetterThan((ObjectStamp) other.stamp()); + } + + /** + * Porcelain method for internal use only, invoked upon a Facade method being notified about + * checkcast or instanceof. + * + * @return whether the state was updated (iff the observation adds any new information) + */ + private boolean refinesSeenType(ResolvedJavaType observed) { + if (cluelessAboutType() || FlowUtil.isMorePrecise(observed, seen)) { + seen = observed; + return true; + } + return false; + } + + /** + * Updates this {@link Witness Witness} to account for an observation about the scrutinee being + * non-null. In case instanceof was observed, + * {@link #trackIO(com.oracle.graal.api.meta.ResolvedJavaType, com.oracle.graal.nodes.extended.GuardingNode) + * trackIO(ResolvedJavaType, GuardingNode)} should be invoked instead + * + * @return whether this {@link Witness Witness} was updated (iff the observation adds any new + * information) + */ + public boolean trackNN(GuardingNode anchor) { + assert repOK(); + try { + if (atInstanceOf()) { + return false; + } + if (atCheckCast()) { + transition(LEVEL.IO, anchor); + return true; + } + if (!atNonNull()) { + transition(LEVEL.NN, anchor); + return true; + } + return false; + } finally { + assert repOK(); + } + } + + /** + * Updates this {@link Witness Witness} to account for an observation about the scrutinee + * conforming to the provided type. In case instanceof was observed, + * {@link #trackIO(com.oracle.graal.api.meta.ResolvedJavaType, com.oracle.graal.nodes.extended.GuardingNode) + * trackIO(ResolvedJavaType, GuardingNode)} should be invoked instead. + * + * @return true iff information was gained. + */ + public boolean trackCC(ResolvedJavaType observed, GuardingNode anchor) { + assert !observed.isInterface(); + assert anchor != null; + assert repOK(); + try { + boolean anchorObsolete = refinesSeenType(observed); + if (atInstanceOf()) { + /* + * Statechart: self-transition at IO, potential information gain. + */ + if (anchorObsolete) { + transition(LEVEL.IO, anchor); + return true; + } + return false; + } + if (anchorObsolete) { + if (!atNonNull()) { + /* Statechart: transition from clueless to CC. */ + transition(LEVEL.CC, anchor); + return true; + } else { + /* Statechart: transition from NN to IO. */ + transition(LEVEL.IO, anchor); + return true; + } + } + /* + * Statechart: self-transition from whichever the current state is to itself, without + * information gain. + */ + return false; + } finally { + assert repOK(); + } + } + + /** + * Updates this {@link Witness Witness} to account for an observation about the non-null + * scrutinee conforming to a type. + * + * @return whether this {@link Witness Witness} was updated (iff the observation adds any new + * information) + */ + public boolean trackIO(ResolvedJavaType observed, GuardingNode anchor) { + assert repOK(); + try { + boolean gotMorePreciseType = refinesSeenType(observed); + if (!atInstanceOf() || gotMorePreciseType) { + transition(LEVEL.IO, anchor); + return true; + } + return gotMorePreciseType; + } finally { + assert repOK(); + } + } + + /** + * Shallow cloning is enough because what's reachable from {@link Witness} is primitive or used + * read-only when merging states. + * */ + @Override + public Witness clone() { + return new Witness(this); + } + + /** + * @return null for a clueless method, non-null otherwise. + * */ + GuardingNode guard() { + return gn; + } + + /** + * Merges another state into this one, by mutating this object, the other is left as is. + * */ + public void merge(Witness that, MergeNode merge) { + assert this.repOK(); + assert that.repOK(); + + if (clueless()) { + return; + } + + // umbrella type over the observations from both witnesses + ResolvedJavaType newSeen = (seen == null || that.seen == null) ? null : FlowUtil.widen(seen, that.seen); + + // preserve guarding node only if matches other, otherwise settle on `merge` + final GuardingNode resultGuard = guard() == that.guard() ? guard() : merge; + + /* + * guarantee on (both conformance and non-nullness) required from each input in order for + * the result to be able to offer such guarantee + */ + final boolean resultIO = atInstanceOf() && that.atInstanceOf(); + /* failing that, attempt to rescue type-conformance */ + final boolean resultCC = !resultIO && (!cluelessAboutType() && !that.cluelessAboutType()); + /* if all else fails, attempt to rescue non-nullness */ + final boolean resultNN = !resultIO && !resultCC && (isNonNull() && that.isNonNull()); + + seen = newSeen; + level = resultIO ? LEVEL.IO : resultCC ? LEVEL.CC : resultNN ? LEVEL.NN : LEVEL.CLUELESS; + gn = resultGuard; + + assert repOK(); + } + + @Override + public String toString() { + StringBuilder sb = new StringBuilder(); + sb.append(cluelessAboutType() ? "seen=?" : "seen=" + seen); + sb.append(";"); + sb.append("gn=" + gn); + return sb.toString(); + } + +} diff -r 3dde8d8c95b8 -r 40d0022115ee 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 Fri Apr 25 16:21:07 2014 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,283 +0,0 @@ -/* - * Copyright (c) 2009, 2014, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -package com.oracle.graal.phases; - -import com.oracle.graal.options.*; - -/** - * This class encapsulates options that control the behavior of the Graal compiler. - */ -// @formatter:off -public final class GraalOptions { - - @Option(help = "Use baseline compiler configuration") - public static final OptionValue UseBaselineCompiler = new OptionValue<>(false); - @Option(help = "Enable use of compiler intrinsics") - public static final OptionValue Intrinsify = new OptionValue<>(true); - @Option(help = "Enable inlining of monomorphic calls") - static final OptionValue InlineMonomorphicCalls = new OptionValue<>(true); - @Option(help = "Enable inlining of polymorphic calls") - static final OptionValue InlinePolymorphicCalls = new OptionValue<>(true); - @Option(help = "Enable inlining of megamorphic calls") - static final OptionValue InlineMegamorphicCalls = new OptionValue<>(true); - @Option(help = "") - public static final OptionValue MegamorphicInliningMinMethodProbability = new OptionValue<>(0.33D); - @Option(help = "") - public static final OptionValue MaximumDesiredSize = new OptionValue<>(20000); - @Option(help = "") - public static final OptionValue MaximumRecursiveInlining = new OptionValue<>(5); - - // inlining settings - @Option(help = "") - public static final OptionValue BoostInliningForEscapeAnalysis = new OptionValue<>(2f); - @Option(help = "") - public static final OptionValue RelevanceCapForInlining = new OptionValue<>(1f); - @Option(help = "") - public static final OptionValue CapInheritedRelevance = new OptionValue<>(1f); - @Option(help = "") - public static final OptionValue IterativeInlining = new OptionValue<>(false); - - @Option(help = "") - public static final OptionValue TrivialInliningSize = new OptionValue<>(10); - @Option(help = "") - public static final OptionValue MaximumInliningSize = new OptionValue<>(300); - @Option(help = "") - public static final OptionValue SmallCompiledLowLevelGraphSize = new OptionValue<>(300); - @Option(help = "") - public static final OptionValue LimitInlinedInvokes = new OptionValue<>(5.0); - @Option(help = "") - public static final OptionValue InlineEverything = new OptionValue<>(false); - - // escape analysis settings - @Option(help = "") - public static final OptionValue PartialEscapeAnalysis = new OptionValue<>(true); - @Option(help = "") - public static final OptionValue EscapeAnalysisIterations = new OptionValue<>(2); - @Option(help = "") - public static final OptionValue EscapeAnalyzeOnly = new OptionValue<>(null); - @Option(help = "") - public static final OptionValue MaximumEscapeAnalysisArrayLength = new OptionValue<>(32); - @Option(help = "") - public static final OptionValue PEAInliningHints = new OptionValue<>(false); - - @Option(help = "") - public static final OptionValue TailDuplicationProbability = new OptionValue<>(0.5); - @Option(help = "") - public static final OptionValue TailDuplicationTrivialSize = new OptionValue<>(1); - - // profiling information - @Option(help = "") - public static final OptionValue DeoptsToDisableOptimisticOptimization = new OptionValue<>(40); - - // graph caching - @Option(help = "") - public static final OptionValue CacheGraphs = new OptionValue<>(true); - - //loop transform settings TODO (gd) tune - @Option(help = "") - public static final OptionValue LoopPeeling = new OptionValue<>(true); - @Option(help = "") - public static final OptionValue ReassociateInvariants = new OptionValue<>(true); - @Option(help = "") - public static final OptionValue FullUnroll = new OptionValue<>(true); - @Option(help = "") - public static final OptionValue LoopUnswitch = new OptionValue<>(true); - @Option(help = "") - public static final OptionValue FullUnrollMaxNodes = new OptionValue<>(300); - @Option(help = "") - public static final OptionValue ExactFullUnrollMaxNodes = new OptionValue<>(1200); - @Option(help = "") - public static final OptionValue MinimumPeelProbability = new OptionValue<>(0.35f); - @Option(help = "") - public static final OptionValue LoopMaxUnswitch = new OptionValue<>(3); - @Option(help = "") - public static final OptionValue LoopUnswitchMaxIncrease = new OptionValue<>(50); - @Option(help = "") - public static final OptionValue LoopUnswitchUncertaintyBoost = new OptionValue<>(5); - @Option(help = "") - public static final OptionValue UseLoopLimitChecks = new OptionValue<>(true); - - // debugging settings - @Option(help = "") - public static final OptionValue ZapStackOnMethodEntry = new OptionValue<>(false); - @Option(help = "") - public static final OptionValue DeoptALot = new OptionValue<>(false); - @Option(help = "") - public static final OptionValue VerifyPhases = new OptionValue<>(false); - - @Option(help = "") - public static final OptionValue PrintFilter = new OptionValue<>(null); - - // Debug settings: - @Option(help = "") - public static final OptionValue BootstrapReplacements = new OptionValue<>(false); - @Option(help = "") - public static final OptionValue GCDebugStartCycle = new OptionValue<>(-1); - // Ideal graph visualizer output settings - @Option(help = "Dump IdealGraphVisualizer output in binary format") - public static final OptionValue PrintBinaryGraphs = new OptionValue<>(true); - @Option(help = "Output probabilities for fixed nodes during binary graph dumping") - public static final OptionValue PrintGraphProbabilities = new OptionValue<>(false); - @Option(help = "Enable dumping to the C1Visualizer. Enabling this option implies PrintBackendCFG.") - public static final OptionValue PrintCFG = new OptionValue<>(false); - @Option(help = "Enable dumping LIR, register allocation and code generation info to the C1Visualizer.") - public static final OptionValue PrintBackendCFG = new OptionValue<>(true); - @Option(help = "") - public static final OptionValue PrintIdealGraphFile = new OptionValue<>(false); - @Option(help = "") - public static final OptionValue PrintIdealGraphAddress = new OptionValue<>("127.0.0.1"); - @Option(help = "") - public static final OptionValue PrintIdealGraphPort = new OptionValue<>(4444); - @Option(help = "") - public static final OptionValue PrintBinaryGraphPort = new OptionValue<>(4445); - - // Other printing settings - @Option(help = "") - public static final OptionValue PrintCompilation = new OptionValue<>(false); - @Option(help = "") - public static final OptionValue PrintAfterCompilation = new OptionValue<>(false); - @Option(help = "Print profiling information when parsing a method's bytecode") - public static final OptionValue PrintProfilingInformation = new OptionValue<>(false); - @Option(help = "") - public static final OptionValue PrintCodeBytes = new OptionValue<>(false); - @Option(help = "") - public static final OptionValue PrintBailout = new OptionValue<>(false); - @Option(help = "") - public static final OptionValue TraceEscapeAnalysis = new OptionValue<>(false); - @Option(help = "") - public static final OptionValue ExitVMOnBailout = new OptionValue<>(false); - @Option(help = "") - public static final OptionValue ExitVMOnException = new OptionValue<>(true); - @Option(help = "") - public static final OptionValue PrintStackTraceOnException = new OptionValue<>(false); - @Option(help = "Set a phase after which the decompiler dumps the graph, -G:Dump= required") - public static final OptionValue DecompileAfterPhase = new OptionValue<>(null); - - // HotSpot command line options - @Option(help = "") - public static final OptionValue HotSpotPrintCompilation = new OptionValue<>(false); - @Option(help = "") - public static final OptionValue HotSpotCIPrintCompilerName = new OptionValue<>(false); - @Option(help = "") - public static final OptionValue HotSpotPrintInlining = new OptionValue<>(false); - - // Register allocator debugging - @Option(help = "") - public static final OptionValue RegisterPressure = new OptionValue<>(null); - - // Code generator settings - @Option(help = "") - public static final OptionValue ConditionalElimination = new OptionValue<>(true); - @Option(help = "") - public static final OptionValue UseProfilingInformation = new OptionValue<>(true); - @Option(help = "") - static final OptionValue RemoveNeverExecutedCode = new OptionValue<>(true); - @Option(help = "") - static final OptionValue UseExceptionProbability = new OptionValue<>(true); - @Option(help = "") - static final OptionValue UseExceptionProbabilityForOperations = new OptionValue<>(true); - @Option(help = "") - public static final OptionValue OmitHotExceptionStacktrace = new OptionValue<>(false); - @Option(help = "") - public static final OptionValue GenSafepoints = new OptionValue<>(true); - @Option(help = "") - public static final OptionValue GenLoopSafepoints = new OptionValue<>(true); - @Option(help = "") - static final OptionValue UseTypeCheckHints = new OptionValue<>(true); - @Option(help = "") - public static final OptionValue InlineVTableStubs = new OptionValue<>(true); - @Option(help = "") - public static final OptionValue AlwaysInlineVTableStubs = new OptionValue<>(false); - @Option(help = "") - public static final OptionValue GenAssertionCode = new OptionValue<>(false); - @Option(help = "") - public static final OptionValue AlignCallsForPatching = new OptionValue<>(true); - @Option(help = "") - public static final OptionValue ResolveClassBeforeStaticInvoke = new OptionValue<>(false); - @Option(help = "") - public static final OptionValue CanOmitFrame = new OptionValue<>(true); - - @Option(help = "") - public static final OptionValue MemoryAwareScheduling = new OptionValue<>(true); - - // Translating tableswitch instructions - @Option(help = "") - public static final OptionValue MinimumJumpTableSize = new OptionValue<>(5); - @Option(help = "") - public static final OptionValue RangeTestsSwitchDensity = new OptionValue<>(5); - @Option(help = "") - public static final OptionValue MinTableSwitchDensity = new OptionValue<>(0.5); - - // Ahead of time compilation - @Option(help = "Try to avoid emitting code where patching is required") - public static final OptionValue ImmutableCode = new OptionValue<>(false); - - @Option(help = "") - public static final OptionValue CallArrayCopy = new OptionValue<>(true); - - // Runtime settings - @Option(help = "") - public static final OptionValue SupportJsrBytecodes = new OptionValue<>(true); - - @Option(help = "") - public static final OptionValue OptAssumptions = new OptionValue<>(true); - @Option(help = "") - public static final OptionValue OptConvertDeoptsToGuards = new OptionValue<>(true); - @Option(help = "") - public static final OptionValue OptReadElimination = new OptionValue<>(true); - @Option(help = "") - public static final OptionValue OptCanonicalizer = new OptionValue<>(true); - @Option(help = "") - public static final OptionValue OptDeoptimizationGrouping = new OptionValue<>(true); - @Option(help = "") - public static final OptionValue OptScheduleOutOfLoops = new OptionValue<>(true); - @Option(help = "") - public static final OptionValue OptEliminateGuards = new OptionValue<>(true); - @Option(help = "") - public static final OptionValue OptImplicitNullChecks = new OptionValue<>(true); - @Option(help = "") - public static final OptionValue OptLivenessAnalysis = new OptionValue<>(true); - @Option(help = "") - public static final OptionValue OptLoopTransform = new OptionValue<>(true); - @Option(help = "") - public static final OptionValue OptFloatingReads = new OptionValue<>(true); - @Option(help = "") - public static final OptionValue OptTailDuplication = new OptionValue<>(true); - @Option(help = "") - public static final OptionValue OptEliminatePartiallyRedundantGuards = new OptionValue<>(true); - @Option(help = "") - public static final OptionValue OptFilterProfiledTypes = new OptionValue<>(true); - @Option(help = "") - public static final OptionValue OptDevirtualizeInvokesOptimistically = new OptionValue<>(true); - @Option(help = "") - public static final OptionValue OptPushThroughPi = new OptionValue<>(true); - @Option(help = "Allow backend to emit arithmetic and compares directly against memory.") - public static final OptionValue OptFoldMemory = new OptionValue<>(true); - - - /** - * Counts the various paths taken through snippets. - */ - @Option(help = "") - public static final OptionValue SnippetCounters = new OptionValue<>(false); -} diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.phases/src/com/oracle/graal/phases/OptimisticOptimizations.java --- a/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/OptimisticOptimizations.java Fri Apr 25 16:21:07 2014 +0200 +++ b/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/OptimisticOptimizations.java Mon Apr 28 11:18:15 2014 +0200 @@ -25,6 +25,7 @@ import java.util.*; import com.oracle.graal.api.meta.*; +import com.oracle.graal.compiler.common.*; import com.oracle.graal.debug.*; public final class OptimisticOptimizations { diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.phases/src/com/oracle/graal/phases/graph/ComputeInliningRelevanceClosure.java --- a/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/graph/ComputeInliningRelevanceClosure.java Fri Apr 25 16:21:07 2014 +0200 +++ b/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/graph/ComputeInliningRelevanceClosure.java Mon Apr 28 11:18:15 2014 +0200 @@ -24,6 +24,7 @@ import java.util.*; +import com.oracle.graal.compiler.common.cfg.*; import com.oracle.graal.graph.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.cfg.*; @@ -105,26 +106,26 @@ private Scope[] computeScopes() { ControlFlowGraph cfg = ControlFlowGraph.compute(graph, true, true, false, false); - Loop[] loops = cfg.getLoops(); - HashMap processedScopes = new HashMap<>(); - Scope[] result = new Scope[loops.length + 1]; + List> loops = cfg.getLoops(); + HashMap, Scope> processedScopes = new HashMap<>(); + Scope[] result = new Scope[loops.size() + 1]; Scope methodScope = new Scope(graph.start(), null); processedScopes.put(null, methodScope); result[0] = methodScope; - for (int i = 0; i < loops.length; i++) { - result[i + 1] = createScope(loops[i], processedScopes); + for (int i = 0; i < loops.size(); i++) { + result[i + 1] = createScope(loops.get(i), processedScopes); } return result; } - private Scope createScope(Loop loop, HashMap processedLoops) { + private Scope createScope(Loop loop, HashMap, Scope> processedLoops) { Scope parent = processedLoops.get(loop.parent); if (parent == null) { parent = createScope(loop.parent, processedLoops); } - Scope result = new Scope(loop.loopBegin(), parent); + Scope result = new Scope(loop.header.getBeginNode(), parent); processedLoops.put(loop, result); return result; } @@ -171,7 +172,7 @@ int pathBeginCount = pathBeginNodes.size(); for (Node sux : controlSplit.successors()) { - double probability = controlSplit.probability((AbstractBeginNode) sux); + double probability = controlSplit.probability((BeginNode) sux); if (probability > maxProbability) { maxProbability = probability; maxSux = sux; diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.phases/src/com/oracle/graal/phases/graph/ComputeProbabilityClosure.java --- a/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/graph/ComputeProbabilityClosure.java Fri Apr 25 16:21:07 2014 +0200 +++ b/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/graph/ComputeProbabilityClosure.java Mon Apr 28 11:18:15 2014 +0200 @@ -223,7 +223,7 @@ } @Override - public void afterSplit(AbstractBeginNode node) { + public void afterSplit(BeginNode node) { assert node.predecessor() != null; Node pred = node.predecessor(); ControlSplitNode x = (ControlSplitNode) pred; diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.phases/src/com/oracle/graal/phases/graph/InferStamps.java --- a/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/graph/InferStamps.java Fri Apr 25 16:21:07 2014 +0200 +++ b/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/graph/InferStamps.java Mon Apr 28 11:18:15 2014 +0200 @@ -22,10 +22,10 @@ */ package com.oracle.graal.phases.graph; +import com.oracle.graal.compiler.common.type.*; import com.oracle.graal.graph.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.spi.*; -import com.oracle.graal.nodes.type.*; public class InferStamps { diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.phases/src/com/oracle/graal/phases/graph/MergeableState.java --- a/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/graph/MergeableState.java Fri Apr 25 16:21:07 2014 +0200 +++ b/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/graph/MergeableState.java Mon Apr 28 11:18:15 2014 +0200 @@ -58,7 +58,7 @@ * * @param node the successor of the control split that is about to be visited */ - public void afterSplit(AbstractBeginNode node) { + public void afterSplit(BeginNode node) { // empty default implementation } } diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.phases/src/com/oracle/graal/phases/graph/PostOrderNodeIterator.java --- a/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/graph/PostOrderNodeIterator.java Fri Apr 25 16:21:07 2014 +0200 +++ b/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/graph/PostOrderNodeIterator.java Mon Apr 28 11:18:15 2014 +0200 @@ -43,7 +43,7 @@ public abstract class PostOrderNodeIterator> { private final NodeBitMap visitedEnds; - private final Deque nodeQueue; + private final Deque nodeQueue; private final IdentityHashMap nodeStates; private final FixedNode start; @@ -109,13 +109,13 @@ for (Node node : successors) { if (node != null) { nodeStates.put((FixedNode) node.predecessor(), state); - nodeQueue.addFirst((AbstractBeginNode) node); + nodeQueue.addFirst((BeginNode) node); } } } else { for (Node node : x.successors()) { if (node != null) { - nodeQueue.addFirst((AbstractBeginNode) node); + nodeQueue.addFirst((BeginNode) node); } } } @@ -124,7 +124,7 @@ private FixedNode nextQueuedNode() { int maxIterations = nodeQueue.size(); while (maxIterations-- > 0) { - AbstractBeginNode node = nodeQueue.removeFirst(); + BeginNode node = nodeQueue.removeFirst(); if (node instanceof MergeNode) { MergeNode merge = (MergeNode) node; state = nodeStates.get(merge.forwardEndAt(0)).clone(); diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.phases/src/com/oracle/graal/phases/graph/ReentrantBlockIterator.java --- a/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/graph/ReentrantBlockIterator.java Fri Apr 25 16:21:07 2014 +0200 +++ b/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/graph/ReentrantBlockIterator.java Mon Apr 28 11:18:15 2014 +0200 @@ -24,6 +24,7 @@ import java.util.*; +import com.oracle.graal.compiler.common.cfg.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.cfg.*; @@ -45,14 +46,14 @@ protected abstract StateT cloneState(StateT oldState); - protected abstract List processLoop(Loop loop, StateT initialState); + protected abstract List processLoop(Loop loop, StateT initialState); } private ReentrantBlockIterator() { // no instances allowed } - public static LoopInfo processLoop(BlockIteratorClosure closure, Loop loop, StateT initialState) { + public static LoopInfo processLoop(BlockIteratorClosure closure, Loop loop, StateT initialState) { IdentityHashMap blockEndStates = apply(closure, loop.header, initialState, new HashSet<>(loop.blocks)); LoopInfo info = new LoopInfo<>(); @@ -101,8 +102,8 @@ states.put(current.getEndNode(), state); } else { // recurse into the loop - Loop loop = successor.getLoop(); - LoopBeginNode loopBegin = loop.loopBegin(); + Loop loop = successor.getLoop(); + LoopBeginNode loopBegin = (LoopBeginNode) loop.header.getBeginNode(); assert successor.getBeginNode() == loopBegin; List exitStates = closure.processLoop(loop, state); diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.phases/src/com/oracle/graal/phases/graph/ReentrantNodeIterator.java --- a/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/graph/ReentrantNodeIterator.java Fri Apr 25 16:21:07 2014 +0200 +++ b/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/graph/ReentrantNodeIterator.java Mon Apr 28 11:18:15 2014 +0200 @@ -41,7 +41,7 @@ protected abstract StateT merge(MergeNode merge, List states); - protected abstract StateT afterSplit(AbstractBeginNode node, StateT oldState); + protected abstract StateT afterSplit(BeginNode node, StateT oldState); protected abstract Map processLoop(LoopBeginNode loop, StateT initialState); @@ -81,7 +81,7 @@ } public static Map apply(NodeIteratorClosure closure, FixedNode start, StateT initialState, Set boundary) { - Deque nodeQueue = new ArrayDeque<>(); + Deque nodeQueue = new ArrayDeque<>(); IdentityHashMap blockEndStates = new IdentityHashMap<>(); StateT state = initialState; @@ -146,14 +146,14 @@ continue; } else { while (successors.hasNext()) { - AbstractBeginNode successor = (AbstractBeginNode) successors.next(); + BeginNode successor = (BeginNode) successors.next(); StateT successorState = closure.afterSplit(successor, state); if (closure.continueIteration(successorState)) { blockEndStates.put(successor, successorState); nodeQueue.add(successor); } } - state = closure.afterSplit((AbstractBeginNode) firstSuccessor, state); + state = closure.afterSplit((BeginNode) firstSuccessor, state); current = closure.continueIteration(state) ? firstSuccessor : null; continue; } @@ -167,7 +167,7 @@ } else { current = nodeQueue.removeFirst(); state = blockEndStates.get(current); - assert !(current instanceof MergeNode) && current instanceof AbstractBeginNode; + assert !(current instanceof MergeNode) && current instanceof BeginNode; } } while (true); } diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.phases/src/com/oracle/graal/phases/graph/StatelessPostOrderNodeIterator.java --- a/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/graph/StatelessPostOrderNodeIterator.java Fri Apr 25 16:21:07 2014 +0200 +++ b/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/graph/StatelessPostOrderNodeIterator.java Mon Apr 28 11:18:15 2014 +0200 @@ -36,7 +36,7 @@ public abstract class StatelessPostOrderNodeIterator { private final NodeBitMap visitedEnds; - private final Deque nodeQueue; + private final Deque nodeQueue; private final FixedNode start; public StatelessPostOrderNodeIterator(FixedNode start) { @@ -76,7 +76,7 @@ controlSplit((ControlSplitNode) current); for (Node node : current.successors()) { if (node != null) { - nodeQueue.addFirst((AbstractBeginNode) node); + nodeQueue.addFirst((BeginNode) node); } } current = nodeQueue.pollFirst(); diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.phases/src/com/oracle/graal/phases/schedule/SchedulePhase.java --- a/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/schedule/SchedulePhase.java Fri Apr 25 16:21:07 2014 +0200 +++ b/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/schedule/SchedulePhase.java Mon Apr 28 11:18:15 2014 +0200 @@ -23,12 +23,14 @@ package com.oracle.graal.phases.schedule; import static com.oracle.graal.api.meta.LocationIdentity.*; +import static com.oracle.graal.compiler.common.GraalOptions.*; import static com.oracle.graal.nodes.cfg.ControlFlowGraph.*; -import static com.oracle.graal.phases.GraalOptions.*; import java.util.*; import com.oracle.graal.api.meta.*; +import com.oracle.graal.compiler.common.*; +import com.oracle.graal.compiler.common.cfg.*; import com.oracle.graal.debug.*; import com.oracle.graal.graph.*; import com.oracle.graal.graph.Node.Verbosity; @@ -152,7 +154,7 @@ } @Override - protected List processLoop(Loop loop, KillSet state) { + protected List processLoop(Loop loop, KillSet state) { LoopInfo info = ReentrantBlockIterator.processLoop(this, loop, cloneState(state)); assert loop.header.getBeginNode() instanceof LoopBeginNode; @@ -201,7 +203,7 @@ } } - AbstractBeginNode startNode = cfg.getStartBlock().getBeginNode(); + BeginNode startNode = cfg.getStartBlock().getBeginNode(); assert startNode instanceof StartNode; KillSet accm = foundExcludeNode ? set : excludedLocations; @@ -649,12 +651,7 @@ * implies that the inputs' blocks have a total ordering via their dominance relation. So in * order to find the earliest block placement for this node we need to find the input block * that is dominated by all other input blocks. - * - * While iterating over the inputs a set of dominator blocks of the current earliest - * placement is maintained. When the block of an input is not within this set, it becomes - * the current earliest placement and the list of dominator blocks is updated. */ - BitSet dominators = new BitSet(cfg.getBlocks().length); if (node.predecessor() != null) { throw new SchedulingError(); @@ -667,12 +664,24 @@ } else { inputEarliest = earliestBlock(input); } - if (!dominators.get(inputEarliest.getId())) { + if (earliest == null) { earliest = inputEarliest; - do { - dominators.set(inputEarliest.getId()); - inputEarliest = inputEarliest.getDominator(); - } while (inputEarliest != null && !dominators.get(inputEarliest.getId())); + } else if (earliest != inputEarliest) { + // Find out whether earliest or inputEarliest is earlier. + Block a = earliest.getDominator(); + Block b = inputEarliest; + while (true) { + if (a == inputEarliest || b == null) { + // Nothing to change, the previous earliest block is still earliest. + break; + } else if (b == earliest || a == null) { + // New earliest is the earliest. + earliest = inputEarliest; + break; + } + a = a.getDominator(); + b = b.getDominator(); + } } } if (earliest == null) { @@ -753,7 +762,7 @@ // If a FrameState is an outer FrameState this method behaves as if the inner // FrameState was the actual usage, by recursing. blocksForUsage(node, unscheduledUsage, closure, strategy); - } else if (unscheduledUsage instanceof AbstractBeginNode) { + } else if (unscheduledUsage instanceof BeginNode) { // Only FrameStates can be connected to BeginNodes. if (!(usage instanceof FrameState)) { throw new SchedulingError(usage.toString()); @@ -922,7 +931,7 @@ } if (canNotMove) { if (b.getEndNode() instanceof ControlSplitNode) { - throw new GraalInternalError("Schedule is not possible : needs to move a node after the last node of the block which can not be move").addContext(lastSorted).addContext( + throw new GraalGraphInternalError("Schedule is not possible : needs to move a node after the last node of the block which can not be move").addContext(lastSorted).addContext( b.getEndNode()); } @@ -977,13 +986,21 @@ stateAfter = ((StateSplit) i).stateAfter(); } + if (i instanceof LoopExitNode) { + for (ProxyNode proxy : ((LoopExitNode) i).proxies()) { + addToLatestSorting(b, proxy, sortedInstructions, visited, reads, beforeLastLocation); + } + } + for (Node input : i.inputs()) { if (input instanceof FrameState) { if (input != stateAfter) { addUnscheduledToLatestSorting(b, (FrameState) input, sortedInstructions, visited, reads, beforeLastLocation); } } else { - addToLatestSorting(b, (ScheduledNode) input, sortedInstructions, visited, reads, beforeLastLocation); + if (!(i instanceof ProxyNode && input instanceof LoopExitNode)) { + addToLatestSorting(b, (ScheduledNode) input, sortedInstructions, visited, reads, beforeLastLocation); + } } } @@ -1047,7 +1064,7 @@ } } - if (instruction instanceof AbstractBeginNode) { + if (instruction instanceof BeginNode) { ArrayList proxies = (instruction instanceof LoopExitNode) ? new ArrayList<>() : null; for (ScheduledNode inBlock : blockToNodesMap.get(b)) { if (!visited.isMarked(inBlock)) { diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.phases/src/com/oracle/graal/phases/tiers/Suites.java --- a/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/tiers/Suites.java Fri Apr 25 16:21:07 2014 +0200 +++ b/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/tiers/Suites.java Mon Apr 28 11:18:15 2014 +0200 @@ -26,7 +26,7 @@ import java.util.*; -import com.oracle.graal.graph.*; +import com.oracle.graal.compiler.common.*; import com.oracle.graal.options.*; import com.oracle.graal.phases.*; diff -r 3dde8d8c95b8 -r 40d0022115ee 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 Fri Apr 25 16:21:07 2014 +0200 +++ b/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/util/GraphOrder.java Mon Apr 28 11:18:15 2014 +0200 @@ -24,10 +24,13 @@ import java.util.*; +import com.oracle.graal.compiler.common.*; +import com.oracle.graal.compiler.common.cfg.*; import com.oracle.graal.graph.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.VirtualState.NodeClosure; import com.oracle.graal.nodes.cfg.*; +import com.oracle.graal.nodes.virtual.*; import com.oracle.graal.phases.graph.*; import com.oracle.graal.phases.graph.ReentrantBlockIterator.BlockIteratorClosure; import com.oracle.graal.phases.schedule.*; @@ -58,8 +61,8 @@ } else { for (Node input : node.inputs()) { if (!visited.isMarked(input)) { - if (input instanceof FrameState && node instanceof StateSplit && input == ((StateSplit) node).stateAfter()) { - // nothing to do - after frame states are known, allowed cycles + if (input instanceof FrameState) { + // nothing to do - frame states are known, allowed cycles } else { assert false : "unexpected cycle detected at input " + node + " -> " + input; } @@ -119,8 +122,7 @@ } } } catch (GraalInternalError e) { - e.addContext(node); - throw e; + throw GraalGraphInternalError.transformAndAddContext(e, node); } } @@ -140,7 +142,7 @@ BlockIteratorClosure closure = new BlockIteratorClosure() { @Override - protected List processLoop(Loop loop, NodeBitMap initialState) { + protected List processLoop(Loop loop, NodeBitMap initialState) { return ReentrantBlockIterator.processLoop(this, loop, initialState).exitStates; } @@ -156,11 +158,15 @@ FrameState pendingStateAfter = null; for (final ScheduledNode node : list) { FrameState stateAfter = node instanceof StateSplit ? ((StateSplit) node).stateAfter() : null; + if (node instanceof InfopointNode) { + stateAfter = ((InfopointNode) node).getState(); + } if (pendingStateAfter != null && node instanceof FixedNode) { pendingStateAfter.applyToNonVirtual(new NodeClosure() { public void apply(Node usage, Node nonVirtualNode) { - assert currentState.isMarked(nonVirtualNode) : nonVirtualNode + " not available at virtualstate " + usage + " before " + node + " in block " + block + " \n" + list; + assert currentState.isMarked(nonVirtualNode) || nonVirtualNode instanceof VirtualObjectNode : nonVirtualNode + " not available at virtualstate " + usage + + " before " + node + " in block " + block + " \n" + list; } }); pendingStateAfter = null; @@ -180,15 +186,23 @@ } } } else if (node instanceof LoopExitNode) { - // the contents of the loop are only accessible via proxies at the exit - currentState.clearAll(); - currentState.markAll(loopEntryStates.get(((LoopExitNode) node).loopBegin())); + if (!graph.isAfterFloatingReadPhase()) { + // loop contents are only accessible via proxies at the exit + currentState.clearAll(); + currentState.markAll(loopEntryStates.get(((LoopExitNode) node).loopBegin())); + } // Loop proxies aren't scheduled, so they need to be added explicitly currentState.markAll(((LoopExitNode) node).proxies()); } else { for (Node input : node.inputs()) { if (input != stateAfter) { - assert currentState.isMarked(input) : input + " not available at " + node + " in block " + block + "\n" + list; + if (input instanceof FrameState) { + ((FrameState) input).applyToNonVirtual((usage, nonVirtual) -> { + assert currentState.isMarked(nonVirtual) : nonVirtual + " not available at " + node + " in block " + block + "\n" + list; + }); + } else { + assert currentState.isMarked(input) || input instanceof VirtualObjectNode : input + " not available at " + node + " in block " + block + "\n" + list; + } } } } diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.phases/src/com/oracle/graal/phases/util/Providers.java --- a/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/util/Providers.java Fri Apr 25 16:21:07 2014 +0200 +++ b/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/util/Providers.java Mon Apr 28 11:18:15 2014 +0200 @@ -24,13 +24,14 @@ import com.oracle.graal.api.code.*; import com.oracle.graal.api.meta.*; +import com.oracle.graal.compiler.common.spi.*; import com.oracle.graal.nodes.spi.*; import com.oracle.graal.phases.tiers.*; /** * A set of providers, some of which may not be present (i.e., null). */ -public class Providers { +public class Providers implements CodeGenProviders { private final MetaAccessProvider metaAccess; private final CodeCacheProvider codeCache; diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.phases/src/com/oracle/graal/phases/verify/VerifyUsageWithEquals.java --- a/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/verify/VerifyUsageWithEquals.java Fri Apr 25 16:21:07 2014 +0200 +++ b/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/verify/VerifyUsageWithEquals.java Mon Apr 28 11:18:15 2014 +0200 @@ -23,6 +23,7 @@ package com.oracle.graal.phases.verify; import com.oracle.graal.api.meta.*; +import com.oracle.graal.compiler.common.type.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.calc.*; import com.oracle.graal.nodes.type.*; @@ -45,7 +46,7 @@ private boolean isAssignableType(ValueNode node, MetaAccessProvider metaAccess) { if (node.stamp() instanceof ObjectStamp) { ResolvedJavaType valueType = metaAccess.lookupJavaType(klass); - ResolvedJavaType nodeType = ObjectStamp.typeOrNull(node); + ResolvedJavaType nodeType = StampTool.typeOrNull(node); if (nodeType != null && valueType.isAssignableFrom(nodeType)) { return true; diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.printer/src/com/oracle/graal/printer/BinaryGraphPrinter.java --- a/graal/com.oracle.graal.printer/src/com/oracle/graal/printer/BinaryGraphPrinter.java Fri Apr 25 16:21:07 2014 +0200 +++ b/graal/com.oracle.graal.printer/src/com/oracle/graal/printer/BinaryGraphPrinter.java Mon Apr 28 11:18:15 2014 +0200 @@ -22,7 +22,7 @@ */ package com.oracle.graal.printer; -import static com.oracle.graal.phases.GraalOptions.*; +import static com.oracle.graal.compiler.common.GraalOptions.*; import java.io.*; import java.nio.*; @@ -31,6 +31,7 @@ import java.util.Map.Entry; import com.oracle.graal.api.meta.*; +import com.oracle.graal.compiler.common.cfg.*; import com.oracle.graal.graph.*; import com.oracle.graal.graph.NodeClass.Position; import com.oracle.graal.nodes.*; @@ -296,13 +297,13 @@ Collection directInputPositions = nodeClass.getFirstLevelInputPositions(); writeShort((char) directInputPositions.size()); for (Position pos : directInputPositions) { - writeByte(pos.subIndex == NodeClass.NOT_ITERABLE ? 0 : 1); + writeByte(pos.getSubIndex() == NodeClass.NOT_ITERABLE ? 0 : 1); writePoolObject(nodeClass.getName(pos)); } Collection directSuccessorPositions = nodeClass.getFirstLevelSuccessorPositions(); writeShort((char) directSuccessorPositions.size()); for (Position pos : directSuccessorPositions) { - writeByte(pos.subIndex == NodeClass.NOT_ITERABLE ? 0 : 1); + writeByte(pos.getSubIndex() == NodeClass.NOT_ITERABLE ? 0 : 1); writePoolObject(nodeClass.getName(pos)); } } else if (object instanceof ResolvedJavaMethod) { @@ -432,7 +433,7 @@ private void writeEdges(Node node, Collection positions) throws IOException { NodeClass nodeClass = node.getNodeClass(); for (Position pos : positions) { - if (pos.subIndex == NodeClass.NOT_ITERABLE) { + if (pos.getSubIndex() == NodeClass.NOT_ITERABLE) { Node edge = nodeClass.get(node, pos); writeNodeRef(edge); } else { diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.printer/src/com/oracle/graal/printer/CFGPrinter.java --- a/graal/com.oracle.graal.printer/src/com/oracle/graal/printer/CFGPrinter.java Fri Apr 25 16:21:07 2014 +0200 +++ b/graal/com.oracle.graal.printer/src/com/oracle/graal/printer/CFGPrinter.java Mon Apr 28 11:18:15 2014 +0200 @@ -31,6 +31,7 @@ import com.oracle.graal.api.meta.*; import com.oracle.graal.compiler.alloc.*; import com.oracle.graal.compiler.alloc.Interval.UsePosList; +import com.oracle.graal.compiler.common.cfg.*; import com.oracle.graal.compiler.gen.*; import com.oracle.graal.graph.*; import com.oracle.graal.graph.Node.Verbosity; @@ -379,12 +380,12 @@ continue; } - if (pos.index != lastIndex) { + if (pos.getIndex() != lastIndex) { if (lastIndex != -1) { out.print(suffix); } out.print(prefix).print(node.getNodeClass().getName(pos)).print(": "); - lastIndex = pos.index; + lastIndex = pos.getIndex(); } out.print(nodeToString(node.getNodeClass().get(node, pos))).print(" "); } @@ -488,7 +489,7 @@ return "-"; } String prefix; - if (node instanceof AbstractBeginNode && (lir == null && schedule == null)) { + if (node instanceof BeginNode && (lir == null && schedule == null)) { prefix = "B"; } else if (node instanceof ValueNode) { ValueNode value = (ValueNode) node; diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.printer/src/com/oracle/graal/printer/CFGPrinterObserver.java --- a/graal/com.oracle.graal.printer/src/com/oracle/graal/printer/CFGPrinterObserver.java Fri Apr 25 16:21:07 2014 +0200 +++ b/graal/com.oracle.graal.printer/src/com/oracle/graal/printer/CFGPrinterObserver.java Mon Apr 28 11:18:15 2014 +0200 @@ -29,6 +29,7 @@ import com.oracle.graal.api.code.*; import com.oracle.graal.api.meta.*; import com.oracle.graal.compiler.alloc.*; +import com.oracle.graal.compiler.common.*; import com.oracle.graal.compiler.gen.*; import com.oracle.graal.debug.*; import com.oracle.graal.graph.*; diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.printer/src/com/oracle/graal/printer/DebugEnvironment.java --- a/graal/com.oracle.graal.printer/src/com/oracle/graal/printer/DebugEnvironment.java Fri Apr 25 16:21:07 2014 +0200 +++ b/graal/com.oracle.graal.printer/src/com/oracle/graal/printer/DebugEnvironment.java Mon Apr 28 11:18:15 2014 +0200 @@ -23,7 +23,7 @@ package com.oracle.graal.printer; import static com.oracle.graal.compiler.GraalDebugConfig.*; -import static com.oracle.graal.phases.GraalOptions.*; +import static com.oracle.graal.compiler.common.GraalOptions.*; import java.io.*; import java.util.*; diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.printer/src/com/oracle/graal/printer/DecompilerDebugDumpHandler.java --- a/graal/com.oracle.graal.printer/src/com/oracle/graal/printer/DecompilerDebugDumpHandler.java Fri Apr 25 16:21:07 2014 +0200 +++ b/graal/com.oracle.graal.printer/src/com/oracle/graal/printer/DecompilerDebugDumpHandler.java Mon Apr 28 11:18:15 2014 +0200 @@ -22,7 +22,7 @@ */ package com.oracle.graal.printer; -import static com.oracle.graal.phases.GraalOptions.*; +import static com.oracle.graal.compiler.common.GraalOptions.*; import java.io.*; import java.util.concurrent.atomic.*; diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.printer/src/com/oracle/graal/printer/GraphPrinterDumpHandler.java --- a/graal/com.oracle.graal.printer/src/com/oracle/graal/printer/GraphPrinterDumpHandler.java Fri Apr 25 16:21:07 2014 +0200 +++ b/graal/com.oracle.graal.printer/src/com/oracle/graal/printer/GraphPrinterDumpHandler.java Mon Apr 28 11:18:15 2014 +0200 @@ -23,7 +23,7 @@ package com.oracle.graal.printer; import static com.oracle.graal.compiler.GraalDebugConfig.*; -import static com.oracle.graal.phases.GraalOptions.*; +import static com.oracle.graal.compiler.common.GraalOptions.*; import java.io.*; import java.net.*; diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.printer/src/com/oracle/graal/printer/IdealGraphPrinter.java --- a/graal/com.oracle.graal.printer/src/com/oracle/graal/printer/IdealGraphPrinter.java Fri Apr 25 16:21:07 2014 +0200 +++ b/graal/com.oracle.graal.printer/src/com/oracle/graal/printer/IdealGraphPrinter.java Mon Apr 28 11:18:15 2014 +0200 @@ -171,7 +171,7 @@ printProperty(bit, "true"); } } - if (node.getClass() == AbstractBeginNode.class) { + if (node.getClass() == BeginNode.class) { printProperty("shortName", "B"); } else if (node.getClass() == AbstractEndNode.class) { printProperty("shortName", "E"); diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.replacements.amd64/src/com/oracle/graal/replacements/amd64/AMD64FloatConvertNode.java --- a/graal/com.oracle.graal.replacements.amd64/src/com/oracle/graal/replacements/amd64/AMD64FloatConvertNode.java Fri Apr 25 16:21:07 2014 +0200 +++ b/graal/com.oracle.graal.replacements.amd64/src/com/oracle/graal/replacements/amd64/AMD64FloatConvertNode.java Mon Apr 28 11:18:15 2014 +0200 @@ -23,12 +23,13 @@ package com.oracle.graal.replacements.amd64; import com.oracle.graal.api.meta.*; -import com.oracle.graal.graph.*; +import com.oracle.graal.compiler.common.*; +import com.oracle.graal.compiler.common.calc.*; +import com.oracle.graal.compiler.common.type.*; +import com.oracle.graal.lir.gen.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.calc.*; -import com.oracle.graal.nodes.calc.FloatConvertNode.FloatConvert; import com.oracle.graal.nodes.spi.*; -import com.oracle.graal.nodes.type.*; /** * This node has the semantics of the AMD64 floating point conversions. It is used in the lowering @@ -51,7 +52,7 @@ throw GraalInternalError.shouldNotReachHere(); } - public void generate(NodeLIRBuilderTool gen) { - gen.setResult(this, gen.getLIRGeneratorTool().emitFloatConvert(op, gen.operand(value))); + public void generate(NodeMappableLIRBuilder builder, ArithmeticLIRGenerator gen) { + builder.setResult(this, gen.emitFloatConvert(op, builder.operand(value))); } } diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.replacements.amd64/src/com/oracle/graal/replacements/amd64/AMD64Substitutions.java --- a/graal/com.oracle.graal.replacements.amd64/src/com/oracle/graal/replacements/amd64/AMD64Substitutions.java Fri Apr 25 16:21:07 2014 +0200 +++ b/graal/com.oracle.graal.replacements.amd64/src/com/oracle/graal/replacements/amd64/AMD64Substitutions.java Mon Apr 28 11:18:15 2014 +0200 @@ -23,10 +23,11 @@ package com.oracle.graal.replacements.amd64; -import static com.oracle.graal.phases.GraalOptions.*; +import static com.oracle.graal.compiler.common.GraalOptions.*; import com.oracle.graal.api.code.*; import com.oracle.graal.api.meta.*; +import com.oracle.graal.api.replacements.*; import com.oracle.graal.api.runtime.*; import com.oracle.graal.nodes.spi.*; import com.oracle.graal.replacements.*; @@ -37,7 +38,7 @@ @ServiceProvider(ReplacementsProvider.class) public class AMD64Substitutions implements ReplacementsProvider { - public void registerReplacements(MetaAccessProvider metaAccess, LoweringProvider lowerer, Replacements replacements, TargetDescription target) { + public void registerReplacements(MetaAccessProvider metaAccess, LoweringProvider lowerer, SnippetReflectionProvider snippetReflection, Replacements replacements, TargetDescription target) { if (Intrinsify.getValue()) { replacements.registerSubstitutions(ArraysSubstitutions.class); replacements.registerSubstitutions(StringSubstitutions.class); diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.replacements.hsail/src/com/oracle/graal/replacements/hsail/HSAILMathIntrinsicsNode.java --- a/graal/com.oracle.graal.replacements.hsail/src/com/oracle/graal/replacements/hsail/HSAILMathIntrinsicsNode.java Fri Apr 25 16:21:07 2014 +0200 +++ b/graal/com.oracle.graal.replacements.hsail/src/com/oracle/graal/replacements/hsail/HSAILMathIntrinsicsNode.java Mon Apr 28 11:18:15 2014 +0200 @@ -23,14 +23,16 @@ package com.oracle.graal.replacements.hsail; import com.oracle.graal.api.meta.*; +import com.oracle.graal.compiler.common.*; +import com.oracle.graal.compiler.common.type.*; import com.oracle.graal.compiler.hsail.*; import com.oracle.graal.graph.*; import com.oracle.graal.graph.spi.*; +import com.oracle.graal.lir.gen.*; import com.oracle.graal.lir.hsail.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.calc.*; import com.oracle.graal.nodes.spi.*; -import com.oracle.graal.nodes.type.*; /** * This node implements HSAIL intrinsics for specific {@link Math} routines. @@ -49,7 +51,7 @@ /** * Gets the parameter passed to the math operation that this node represents. - * + * * @return the parameter */ public ValueNode getParameter() { @@ -58,7 +60,7 @@ /** * Returns the math operation represented by this node. - * + * * @return the operation */ public HSAILArithmetic operation() { @@ -67,7 +69,7 @@ /** * Creates a new HSAILMathIntrinsicNode. - * + * * @param x the argument to the math operation * @param op the math operation */ @@ -81,30 +83,30 @@ * Generates the LIR instructions for the math operation represented by this node. */ @Override - public void generate(NodeLIRBuilderTool gen) { - Value input = gen.operand(getParameter()); + public void generate(NodeMappableLIRBuilder builder, ArithmeticLIRGenerator gen) { + Value input = builder.operand(getParameter()); Value result; switch (operation()) { case ABS: - result = gen.getLIRGeneratorTool().emitMathAbs(input); + result = gen.emitMathAbs(input); break; case CEIL: - result = ((HSAILLIRGenerator) (gen.getLIRGeneratorTool())).emitMathCeil(input); + result = ((HSAILLIRGenerator) gen).emitMathCeil(input); break; case FLOOR: - result = ((HSAILLIRGenerator) (gen.getLIRGeneratorTool())).emitMathFloor(input); + result = ((HSAILLIRGenerator) gen).emitMathFloor(input); break; case RINT: - result = ((HSAILLIRGenerator) (gen.getLIRGeneratorTool())).emitMathRint(input); + result = ((HSAILLIRGenerator) gen).emitMathRint(input); break; case SQRT: - result = gen.getLIRGeneratorTool().emitMathSqrt(input); + result = gen.emitMathSqrt(input); break; default: throw GraalInternalError.shouldNotReachHere(); } - gen.setResult(this, result); + builder.setResult(this, result); } /** @@ -132,7 +134,7 @@ /** * Node intrinsic for {@link Math} routines taking a single int parameter. - * + * * @param value * @param op the math operation * @return the result of the operation @@ -142,7 +144,7 @@ /** * Node intrinsic for {@link Math} routines taking a single double parameter. - * + * * @param value the input parameter * @param op the math operation * @return the result of the operation @@ -152,7 +154,7 @@ /** * Node intrinsic for {@link Math} routines taking a single float parameter. - * + * * @param value the input parameter * @param op the math operation * @return the result of the operation @@ -162,10 +164,10 @@ /** * Node intrinsic for {@link Math} routines taking a single double parameter. - * + * * @param value the input parameter * @param op the math operation - * + * * @return the result of the operation */ @NodeIntrinsic diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/test/CheckCastTest.java --- a/graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/test/CheckCastTest.java Fri Apr 25 16:21:07 2014 +0200 +++ b/graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/test/CheckCastTest.java Mon Apr 28 11:18:15 2014 +0200 @@ -22,10 +22,11 @@ */ package com.oracle.graal.replacements.test; +import org.junit.*; + import com.oracle.graal.api.meta.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.java.*; -import com.oracle.graal.test.*; /** * Tests the implementation of checkcast, allowing profiling information to be manually specified. @@ -41,7 +42,7 @@ } } - @LongTest + @Test public void test1() { test("asNumber", profile(), 111); test("asNumber", profile(Integer.class), 111); @@ -51,7 +52,7 @@ test("asNumberExt", profile(Long.class, Short.class), 111); } - @LongTest + @Test public void test2() { test("asString", profile(), "111"); test("asString", profile(String.class), "111"); @@ -67,27 +68,27 @@ test("asStringExt", profile(String.class), "111"); } - @LongTest + @Test public void test3() { test("asNumber", profile(), "111"); } - @LongTest + @Test public void test4() { test("asString", profile(String.class), 111); } - @LongTest + @Test public void test5() { test("asNumberExt", profile(), "111"); } - @LongTest + @Test public void test6() { test("asStringExt", profile(String.class), 111); } - @LongTest + @Test public void test7() { Throwable throwable = new Exception(); test("asThrowable", profile(), throwable); @@ -95,12 +96,12 @@ test("asThrowable", profile(Exception.class, Error.class), throwable); } - @LongTest + @Test public void test8() { test("arrayStore", new Object[100], "111"); } - @LongTest + @Test public void test801() { test("arrayFill", new Object[100], "111"); } @@ -197,7 +198,7 @@ return (Cloneable) o; } - @LongTest + @Test public void test9() { Object o = new Depth13(); test("asDepth12", profile(), o); @@ -205,7 +206,7 @@ test("asDepth12", profile(Depth13.class, Depth14.class), o); } - @LongTest + @Test public void test10() { Object o = new Depth13[3][]; test("asDepth12Arr", o); diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/test/InstanceOfDynamicTest.java --- a/graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/test/InstanceOfDynamicTest.java Fri Apr 25 16:21:07 2014 +0200 +++ b/graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/test/InstanceOfDynamicTest.java Mon Apr 28 11:18:15 2014 +0200 @@ -22,9 +22,10 @@ */ package com.oracle.graal.replacements.test; +import org.junit.*; + import com.oracle.graal.compiler.test.*; import com.oracle.graal.nodes.java.*; -import com.oracle.graal.test.*; /** * Tests for {@link InstanceOfDynamicNode}. @@ -35,7 +36,7 @@ return value; } - @LongTest + @Test public void test100() { final Object nul = null; test("isStringDynamic", nul); @@ -43,7 +44,7 @@ test("isStringDynamic", Object.class); } - @LongTest + @Test public void test101() { final Object nul = null; test("isStringIntDynamic", nul); @@ -51,7 +52,7 @@ test("isStringIntDynamic", Object.class); } - @LongTest + @Test public void test103() { test("isInstanceDynamic", String.class, null); test("isInstanceDynamic", String.class, "object"); @@ -61,7 +62,7 @@ test("isInstanceDynamic", int.class, Object.class); } - @LongTest + @Test public void test104() { test("isInstanceIntDynamic", String.class, null); test("isInstanceIntDynamic", String.class, "object"); diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/test/InstanceOfTest.java --- a/graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/test/InstanceOfTest.java Fri Apr 25 16:21:07 2014 +0200 +++ b/graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/test/InstanceOfTest.java Mon Apr 28 11:18:15 2014 +0200 @@ -24,6 +24,8 @@ import java.util.*; +import org.junit.*; + import com.oracle.graal.api.code.CompilationResult.Call; import com.oracle.graal.api.code.CompilationResult.Mark; import com.oracle.graal.api.code.CompilationResult.Site; @@ -34,7 +36,6 @@ import com.oracle.graal.replacements.test.CheckCastTest.Depth12; import com.oracle.graal.replacements.test.CheckCastTest.Depth13; import com.oracle.graal.replacements.test.CheckCastTest.Depth14; -import com.oracle.graal.test.*; /** * Tests the implementation of instanceof, allowing profiling information to be manually specified. @@ -54,7 +55,7 @@ } } - @LongTest + @Test public void test1() { test("isString", profile(), "object"); test("isString", profile(String.class), "object"); @@ -63,7 +64,7 @@ test("isString", profile(String.class), Object.class); } - @LongTest + @Test public void test2() { test("isStringInt", profile(), "object"); test("isStringInt", profile(String.class), "object"); @@ -72,7 +73,7 @@ test("isStringInt", profile(String.class), Object.class); } - @LongTest + @Test public void test201() { test("isStringIntComplex", profile(), "object"); test("isStringIntComplex", profile(String.class), "object"); @@ -81,7 +82,7 @@ test("isStringIntComplex", profile(String.class), Object.class); } - @LongTest + @Test public void test3() { Throwable throwable = new Exception(); test("isThrowable", profile(), throwable); @@ -93,7 +94,7 @@ test("isThrowable", profile(Exception.class, Error.class), Object.class); } - @LongTest + @Test public void test301() { onlyFirstIsException(new Exception(), new Error()); test("onlyFirstIsException", profile(), new Exception(), new Error()); @@ -102,7 +103,7 @@ test("onlyFirstIsException", profile(), new Error(), new Error()); } - @LongTest + @Test public void test4() { Throwable throwable = new Exception(); test("isThrowableInt", profile(), throwable); @@ -114,7 +115,7 @@ test("isThrowableInt", profile(Exception.class, Error.class), Object.class); } - @LongTest + @Test public void test5() { Map map = new HashMap<>(); test("isMap", profile(), map); @@ -127,7 +128,7 @@ test("isMap", profile(String.class, HashMap.class), Object.class); } - @LongTest + @Test public void test6() { Map map = new HashMap<>(); test("isMapInt", profile(), map); @@ -139,7 +140,7 @@ test("isMapInt", profile(TreeMap.class, HashMap.class), Object.class); } - @LongTest + @Test public void test7() { Object o = new Depth13(); test("isDepth12", profile(), o); @@ -153,7 +154,7 @@ test("isDepth12", profile(String.class, HashMap.class), o); } - @LongTest + @Test public void test8() { Object o = new Depth13(); test("isDepth12Int", profile(), o); @@ -259,7 +260,7 @@ } } - @LongTest + @Test public void test9() { MyCall callAt63 = new MyCall(63); MyMark markAt63 = new MyMark(63); @@ -276,11 +277,10 @@ return s1.offset - s2.offset; } - @LongTest + @Test public void test10() { - Mark[] noMarks = {}; Call callAt63 = new Call(null, 63, 5, true, null); - Mark markAt63 = new Mark(63, "1", noMarks); + Mark markAt63 = new Mark(63, "1"); test("compareSites", callAt63, callAt63); test("compareSites", callAt63, markAt63); test("compareSites", markAt63, callAt63); @@ -301,7 +301,7 @@ * The test exists in this source file as the transformation was originally motivated by the * need to remove use of special JumpNodes in the {@code InstanceOfSnippets}. */ - @LongTest + @Test public void testRemoveIntermediateMaterialization() { List list = Arrays.asList("1", "2", "3", "4"); test("removeIntermediateMaterialization", profile(), list, "2", "yes", "no"); @@ -356,7 +356,7 @@ return o instanceof D[]; } - @LongTest + @Test public void testArray() { Object aArray = new A[10]; test("isArrayOfA", aArray); diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/test/NewArrayTest.java --- a/graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/test/NewArrayTest.java Fri Apr 25 16:21:07 2014 +0200 +++ b/graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/test/NewArrayTest.java Mon Apr 28 11:18:15 2014 +0200 @@ -25,7 +25,6 @@ import org.junit.*; import com.oracle.graal.compiler.test.*; -import com.oracle.graal.test.*; /** * Tests the implementation of {@code [A]NEWARRAY}. @@ -58,7 +57,7 @@ } } - @LongTest + @Test public void test1() { for (String type : new String[]{"Byte", "Char", "Short", "Int", "Float", "Long", "Double", "String"}) { test("new" + type + "Array7"); diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/test/NewInstanceTest.java --- a/graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/test/NewInstanceTest.java Fri Apr 25 16:21:07 2014 +0200 +++ b/graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/test/NewInstanceTest.java Mon Apr 28 11:18:15 2014 +0200 @@ -27,7 +27,6 @@ import org.junit.*; import com.oracle.graal.compiler.test.*; -import com.oracle.graal.test.*; /** * Tests the implementation of {@code NEW}. @@ -57,12 +56,12 @@ } } - @LongTest + @Test public void test1() { test("newObject"); } - @LongTest + @Test public void test2() { test("newObjectTwice"); } @@ -71,37 +70,37 @@ return new Object(); } - @LongTest + @Test public void test3() { test("newObjectLoop", 100); } - @LongTest + @Test public void test4() { test("newBigObject"); } - @LongTest + @Test public void test5() { test("newSomeObject"); } - @LongTest + @Test public void test6() { test("newEmptyString"); } - @LongTest + @Test public void test7() { test("newString", "value"); } - @LongTest + @Test public void test8() { test("newHashMap", 31); } - @LongTest + @Test public void test9() { test("newRegression", true); } diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/test/NewMultiArrayTest.java --- a/graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/test/NewMultiArrayTest.java Fri Apr 25 16:21:07 2014 +0200 +++ b/graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/test/NewMultiArrayTest.java Mon Apr 28 11:18:15 2014 +0200 @@ -25,12 +25,13 @@ import java.lang.reflect.*; import java.util.*; +import org.junit.*; + import com.oracle.graal.api.code.*; import com.oracle.graal.api.meta.*; import com.oracle.graal.compiler.test.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.java.*; -import com.oracle.graal.test.*; /** * Tests the lowering of the MULTIANEWARRAY instruction. @@ -86,7 +87,7 @@ Class bottomClass; int[] dimensions; - @LongTest + @Test public void test1() { for (Class clazz : new Class[]{byte.class, char.class, short.class, int.class, float.class, long.class, double.class, String.class}) { bottomClass = clazz; @@ -117,7 +118,7 @@ return new Object[10][9][8]; } - @LongTest + @Test public void test2() { test("newMultiArrayException"); } diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/test/ObjectAccessTest.java --- a/graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/test/ObjectAccessTest.java Fri Apr 25 16:21:07 2014 +0200 +++ b/graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/test/ObjectAccessTest.java Mon Apr 28 11:18:15 2014 +0200 @@ -127,7 +127,7 @@ JavaWriteNode write = (JavaWriteNode) graph.start().next(); Assert.assertEquals(graph.getParameter(2), write.value()); Assert.assertEquals(graph.getParameter(0), write.object()); - Assert.assertEquals(FrameState.AFTER_BCI, write.stateAfter().bci); + Assert.assertEquals(BytecodeFrame.AFTER_BCI, write.stateAfter().bci); IndexedLocationNode location = (IndexedLocationNode) write.location(); Assert.assertEquals(kind, location.getValueKind()); diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/test/PointerTest.java --- a/graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/test/PointerTest.java Fri Apr 25 16:21:07 2014 +0200 +++ b/graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/test/PointerTest.java Mon Apr 28 11:18:15 2014 +0200 @@ -139,7 +139,7 @@ JavaWriteNode write = (JavaWriteNode) cast.next(); Assert.assertEquals(graph.getParameter(2), write.value()); - Assert.assertEquals(FrameState.AFTER_BCI, write.stateAfter().bci); + Assert.assertEquals(BytecodeFrame.AFTER_BCI, write.stateAfter().bci); Assert.assertEquals(cast, write.object()); Assert.assertEquals(graph.getParameter(0), cast.getInput()); diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/test/StandardMethodSubstitutionsTest.java --- a/graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/test/StandardMethodSubstitutionsTest.java Fri Apr 25 16:21:07 2014 +0200 +++ b/graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/test/StandardMethodSubstitutionsTest.java Mon Apr 28 11:18:15 2014 +0200 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2014, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -22,16 +22,10 @@ */ package com.oracle.graal.replacements.test; -import static com.oracle.graal.graph.UnsafeAccess.*; -import static com.oracle.graal.replacements.UnsafeSubstitutions.*; - import java.lang.reflect.*; -import java.util.concurrent.atomic.*; import org.junit.*; -import sun.misc.*; - import com.oracle.graal.api.code.*; import com.oracle.graal.api.replacements.*; import com.oracle.graal.nodes.*; @@ -44,287 +38,6 @@ */ public class StandardMethodSubstitutionsTest extends MethodSubstitutionTest { - static long off(Object o, String name) { - try { - return unsafe.objectFieldOffset(o.getClass().getDeclaredField(name)); - } catch (Exception e) { - Assert.fail(e.toString()); - return 0L; - } - } - - static class Foo { - - boolean z; - byte b; - short s; - char c; - int i; - long l; - float f; - double d; - Object o; - - void testGet(Field field, long offset, String getName, Object value) throws Exception { - field.set(this, value); - Method m1 = Unsafe.class.getDeclaredMethod(getName, Object.class, long.class); - Method m2 = UnsafeSubstitutions.class.getDeclaredMethod(getName, Object.class, Object.class, long.class); - Object expected = m1.invoke(unsafe, this, offset); - Object actual = m2.invoke(null, unsafe, this, offset); - Assert.assertEquals(expected, actual); - } - - void testDirect(Field field, long offset, String type, Object value) throws Exception { - if (type.equals("Boolean") || type.equals("Object")) { - // No direct memory access for these types - return; - } - - long address = unsafe.allocateMemory(offset + 16); - - String getName = "get" + type; - String putName = "put" + type; - Method m1 = Unsafe.class.getDeclaredMethod(putName, long.class, field.getType()); - Method m2 = Unsafe.class.getDeclaredMethod(getName, long.class); - - Method m3 = UnsafeSubstitutions.class.getDeclaredMethod(putName, Object.class, long.class, field.getType()); - Method m4 = UnsafeSubstitutions.class.getDeclaredMethod(getName, Object.class, long.class); - - m1.invoke(unsafe, address + offset, value); - Object expected = m2.invoke(unsafe, address + offset); - - m3.invoke(null, unsafe, address + offset, value); - Object actual = m4.invoke(null, unsafe, address + offset); - - unsafe.freeMemory(address); - Assert.assertEquals(expected, actual); - } - - void testPut(Field field, long offset, String putName, Object value) throws Exception { - Object initialValue = field.get(new Foo()); - field.set(this, initialValue); - - try { - Method m1 = Unsafe.class.getDeclaredMethod(putName, Object.class, long.class, field.getType()); - Method m2 = UnsafeSubstitutions.class.getDeclaredMethod(putName, Object.class, Object.class, long.class, field.getType()); - m1.invoke(unsafe, this, offset, value); - Object expected = field.get(this); - m2.invoke(null, unsafe, this, offset, value); - Object actual = field.get(this); - Assert.assertEquals(expected, actual); - } catch (NoSuchMethodException e) { - if (!putName.startsWith("putOrdered")) { - throw e; - } - } - } - - void test(String fieldName, String typeSuffix, Object value) { - try { - Field field = Foo.class.getDeclaredField(fieldName); - long offset = unsafe.objectFieldOffset(field); - testGet(field, offset, "get" + typeSuffix, value); - testGet(field, offset, "get" + typeSuffix + "Volatile", value); - testPut(field, offset, "put" + typeSuffix, value); - testPut(field, offset, "put" + typeSuffix + "Volatile", value); - testPut(field, offset, "putOrdered" + typeSuffix, value); - testDirect(field, offset, typeSuffix, value); - } catch (Exception e) { - throw new AssertionError(e); - } - } - } - - @Test - public void testUnsafeSubstitutions() throws Exception { - test("unsafeCompareAndSwapInt"); - test("unsafeCompareAndSwapLong"); - test("unsafeCompareAndSwapObject"); - - test("unsafeGetBoolean"); - test("unsafeGetByte"); - test("unsafeGetShort"); - test("unsafeGetChar"); - test("unsafeGetInt"); - test("unsafeGetLong"); - test("unsafeGetFloat"); - test("unsafeGetDouble"); - test("unsafeGetObject"); - - test("unsafePutBoolean"); - test("unsafePutByte"); - test("unsafePutShort"); - test("unsafePutChar"); - test("unsafePutInt"); - test("unsafePutFloat"); - test("unsafePutDouble"); - test("unsafePutObject"); - - test("unsafeDirectMemoryRead"); - test("unsafeDirectMemoryWrite"); - - AtomicInteger a1 = new AtomicInteger(42); - AtomicInteger a2 = new AtomicInteger(42); - assertEquals(unsafe.compareAndSwapInt(a1, off(a1, "value"), 42, 53), compareAndSwapInt(unsafe, a2, off(a2, "value"), 42, 53)); - assertEquals(a1.get(), a2.get()); - - AtomicLong l1 = new AtomicLong(42); - AtomicLong l2 = new AtomicLong(42); - assertEquals(unsafe.compareAndSwapLong(l1, off(l1, "value"), 42, 53), compareAndSwapLong(unsafe, l2, off(l2, "value"), 42, 53)); - assertEquals(l1.get(), l2.get()); - - AtomicReference o1 = new AtomicReference<>("42"); - AtomicReference o2 = new AtomicReference<>("42"); - assertEquals(unsafe.compareAndSwapObject(o1, off(o1, "value"), "42", "53"), compareAndSwapObject(unsafe, o2, off(o2, "value"), "42", "53")); - assertEquals(o1.get(), o2.get()); - - Foo f1 = new Foo(); - f1.test("z", "Boolean", Boolean.TRUE); - f1.test("b", "Byte", Byte.MIN_VALUE); - f1.test("s", "Short", Short.MAX_VALUE); - f1.test("c", "Char", '!'); - f1.test("i", "Int", 1010010); - f1.test("f", "Float", -34.5F); - f1.test("l", "Long", 99999L); - f1.test("d", "Double", 1234.5678D); - f1.test("o", "Object", "object"); - } - - @SuppressWarnings("all") - public static boolean unsafeCompareAndSwapInt(Unsafe unsafe, Object obj, long offset) { - return unsafe.compareAndSwapInt(obj, offset, 0, 1); - } - - @SuppressWarnings("all") - public static boolean unsafeCompareAndSwapLong(Unsafe unsafe, Object obj, long offset) { - return unsafe.compareAndSwapLong(obj, offset, 0, 1); - } - - @SuppressWarnings("all") - public static boolean unsafeCompareAndSwapObject(Unsafe unsafe, Object obj, long offset) { - return unsafe.compareAndSwapObject(obj, offset, null, new Object()); - } - - @SuppressWarnings("all") - public static boolean unsafeGetBoolean(Unsafe unsafe, Object obj, long offset) { - return unsafe.getBoolean(obj, offset) && unsafe.getBooleanVolatile(obj, offset); - } - - @SuppressWarnings("all") - public static int unsafeGetByte(Unsafe unsafe, Object obj, long offset) { - return unsafe.getByte(obj, offset) + unsafe.getByteVolatile(obj, offset); - } - - @SuppressWarnings("all") - public static int unsafeGetShort(Unsafe unsafe, Object obj, long offset) { - return unsafe.getShort(obj, offset) + unsafe.getShortVolatile(obj, offset); - } - - @SuppressWarnings("all") - public static int unsafeGetChar(Unsafe unsafe, Object obj, long offset) { - return unsafe.getChar(obj, offset) + unsafe.getCharVolatile(obj, offset); - } - - @SuppressWarnings("all") - public static int unsafeGetInt(Unsafe unsafe, Object obj, long offset) { - return unsafe.getInt(obj, offset) + unsafe.getIntVolatile(obj, offset); - } - - @SuppressWarnings("all") - public static long unsafeGetLong(Unsafe unsafe, Object obj, long offset) { - return unsafe.getLong(obj, offset) + unsafe.getLongVolatile(obj, offset); - } - - @SuppressWarnings("all") - public static float unsafeGetFloat(Unsafe unsafe, Object obj, long offset) { - return unsafe.getFloat(obj, offset) + unsafe.getFloatVolatile(obj, offset); - } - - @SuppressWarnings("all") - public static double unsafeGetDouble(Unsafe unsafe, Object obj, long offset) { - return unsafe.getDouble(obj, offset) + unsafe.getDoubleVolatile(obj, offset); - } - - @SuppressWarnings("all") - public static boolean unsafeGetObject(Unsafe unsafe, Object obj, long offset) { - return unsafe.getObject(obj, offset) == unsafe.getObjectVolatile(obj, offset); - } - - @SuppressWarnings("all") - public static void unsafePutBoolean(Unsafe unsafe, Object obj, long offset, boolean value) { - unsafe.putBoolean(obj, offset, value); - unsafe.putBooleanVolatile(obj, offset, value); - } - - @SuppressWarnings("all") - public static void unsafePutByte(Unsafe unsafe, Object obj, long offset, byte value) { - unsafe.putByte(obj, offset, value); - unsafe.putByteVolatile(obj, offset, value); - } - - @SuppressWarnings("all") - public static void unsafePutShort(Unsafe unsafe, Object obj, long offset, short value) { - unsafe.putShort(obj, offset, value); - unsafe.putShortVolatile(obj, offset, value); - } - - @SuppressWarnings("all") - public static void unsafePutChar(Unsafe unsafe, Object obj, long offset, char value) { - unsafe.putChar(obj, offset, value); - unsafe.putCharVolatile(obj, offset, value); - } - - @SuppressWarnings("all") - public static void unsafePutInt(Unsafe unsafe, Object obj, long offset, int value) { - unsafe.putInt(obj, offset, value); - unsafe.putIntVolatile(obj, offset, value); - unsafe.putOrderedInt(obj, offset, value); - } - - @SuppressWarnings("all") - public static void unsafePutLong(Unsafe unsafe, Object obj, long offset, long value) { - unsafe.putLong(obj, offset, value); - unsafe.putLongVolatile(obj, offset, value); - unsafe.putOrderedLong(obj, offset, value); - } - - @SuppressWarnings("all") - public static void unsafePutFloat(Unsafe unsafe, Object obj, long offset, float value) { - unsafe.putFloat(obj, offset, value); - unsafe.putFloatVolatile(obj, offset, value); - } - - @SuppressWarnings("all") - public static void unsafePutDouble(Unsafe unsafe, Object obj, long offset, double value) { - unsafe.putDouble(obj, offset, value); - unsafe.putDoubleVolatile(obj, offset, value); - } - - @SuppressWarnings("all") - public static void unsafePutObject(Unsafe unsafe, Object obj, long offset, Object value) { - unsafe.putObject(obj, offset, value); - unsafe.putObjectVolatile(obj, offset, value); - unsafe.putOrderedObject(obj, offset, value); - } - - @SuppressWarnings("all") - public static double unsafeDirectMemoryRead(Unsafe unsafe, long address) { - // Unsafe.getBoolean(long) and Unsafe.getObject(long) do not exist - return unsafe.getByte(address) + unsafe.getShort(address) + unsafe.getChar(address) + unsafe.getInt(address) + unsafe.getLong(address) + unsafe.getFloat(address) + unsafe.getDouble(address); - } - - @SuppressWarnings("all") - public static void unsafeDirectMemoryWrite(Unsafe unsafe, long address, byte value) { - // Unsafe.putBoolean(long) and Unsafe.putObject(long) do not exist - unsafe.putByte(address, value); - unsafe.putShort(address, value); - unsafe.putChar(address, (char) value); - unsafe.putInt(address, value); - unsafe.putLong(address, value); - unsafe.putFloat(address, value); - unsafe.putDouble(address, value); - } - @Test public void testMathSubstitutions() { assertInGraph(assertNotInGraph(test("mathAbs"), IfNode.class), MathIntrinsicNode.class); // Java diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/test/UnsafeSubstitutionsTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/test/UnsafeSubstitutionsTest.java Mon Apr 28 11:18:15 2014 +0200 @@ -0,0 +1,451 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.graal.replacements.test; + +import static com.oracle.graal.compiler.common.UnsafeAccess.*; +import static com.oracle.graal.replacements.UnsafeSubstitutions.*; + +import java.lang.reflect.*; +import java.util.concurrent.atomic.*; + +import org.junit.*; + +import sun.misc.*; + +import com.oracle.graal.api.code.*; +import com.oracle.graal.replacements.*; + +/** + * Tests the VM independent {@link UnsafeSubstitutions}. + */ +public class UnsafeSubstitutionsTest extends MethodSubstitutionTest { + + private static Object executeVarargsSafe(InstalledCode code, Object... args) { + try { + return code.executeVarargs(args); + } catch (InvalidInstalledCodeException e) { + throw new RuntimeException(e); + } + } + + private static Object invokeSafe(Method method, Object receiver, Object... args) { + method.setAccessible(true); + try { + return method.invoke(receiver, args); + } catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException e) { + throw new RuntimeException(e); + } + } + + public void testSubstitution(String testMethodName, Class holder, String methodName, Class[] parameterTypes, Object receiver, Object[] args1, Object[] args2) { + Method originalMethod = getMethod(holder, methodName, parameterTypes); + Method testMethod = getMethod(testMethodName); + + // Force compilation + InstalledCode code = getCode(getMetaAccess().lookupJavaMethod(testMethod), parse(testMethod)); + assert code != null; + + // Verify that the original method and the substitution produce the same value + { + Object expected = invokeSafe(originalMethod, receiver, args1); + Object actual = invokeSafe(testMethod, null, args2); + assertEquals(expected, actual); + } + + // Verify that the generated code and the original produce the same value + { + Object expected = invokeSafe(originalMethod, receiver, args1); + Object actual = executeVarargsSafe(code, args2); + assertEquals(expected, actual); + } + } + + static long off(Object o, String name) { + try { + return unsafe.objectFieldOffset(o.getClass().getDeclaredField(name)); + } catch (Exception e) { + Assert.fail(e.toString()); + return 0L; + } + } + + static class Foo { + + boolean z; + byte b; + short s; + char c; + int i; + long l; + float f; + double d; + Object o; + + void testGet(Field field, long offset, String getName, Object value) throws Exception { + field.set(this, value); + Method m1 = Unsafe.class.getDeclaredMethod(getName, Object.class, long.class); + Method m2 = UnsafeSubstitutions.class.getDeclaredMethod(getName, Object.class, Object.class, long.class); + Object expected = m1.invoke(unsafe, this, offset); + Object actual = m2.invoke(null, unsafe, this, offset); + Assert.assertEquals(expected, actual); + } + + void testDirect(Field field, long offset, String type, Object value) throws Exception { + if (type.equals("Boolean") || type.equals("Object")) { + // No direct memory access for these types + return; + } + + long address = unsafe.allocateMemory(offset + 16); + + String getName = "get" + type; + String putName = "put" + type; + Method m1 = Unsafe.class.getDeclaredMethod(putName, long.class, field.getType()); + Method m2 = Unsafe.class.getDeclaredMethod(getName, long.class); + + Method m3 = UnsafeSubstitutions.class.getDeclaredMethod(putName, Object.class, long.class, field.getType()); + Method m4 = UnsafeSubstitutions.class.getDeclaredMethod(getName, Object.class, long.class); + + m1.invoke(unsafe, address + offset, value); + Object expected = m2.invoke(unsafe, address + offset); + + m3.invoke(null, unsafe, address + offset, value); + Object actual = m4.invoke(null, unsafe, address + offset); + + unsafe.freeMemory(address); + Assert.assertEquals(expected, actual); + } + + void testPut(Field field, long offset, String putName, Object value) throws Exception { + Object initialValue = field.get(new Foo()); + field.set(this, initialValue); + + try { + Method m1 = Unsafe.class.getDeclaredMethod(putName, Object.class, long.class, field.getType()); + Method m2 = UnsafeSubstitutions.class.getDeclaredMethod(putName, Object.class, Object.class, long.class, field.getType()); + m1.invoke(unsafe, this, offset, value); + Object expected = field.get(this); + m2.invoke(null, unsafe, this, offset, value); + Object actual = field.get(this); + Assert.assertEquals(expected, actual); + } catch (NoSuchMethodException e) { + if (!putName.startsWith("putOrdered")) { + throw e; + } + } + } + + void test(String fieldName, String typeSuffix, Object value) { + try { + Field field = Foo.class.getDeclaredField(fieldName); + long offset = unsafe.objectFieldOffset(field); + testGet(field, offset, "get" + typeSuffix, value); + testGet(field, offset, "get" + typeSuffix + "Volatile", value); + testPut(field, offset, "put" + typeSuffix, value); + testPut(field, offset, "put" + typeSuffix + "Volatile", value); + testPut(field, offset, "putOrdered" + typeSuffix, value); + testDirect(field, offset, typeSuffix, value); + } catch (Exception e) { + throw new AssertionError(e); + } + } + } + + @Test + public void testUnsafeSubstitutions() throws Exception { + test("unsafeCompareAndSwapInt"); + test("unsafeCompareAndSwapLong"); + test("unsafeCompareAndSwapObject"); + + test("unsafeGetBoolean"); + test("unsafeGetByte"); + test("unsafeGetShort"); + test("unsafeGetChar"); + test("unsafeGetInt"); + test("unsafeGetLong"); + test("unsafeGetFloat"); + test("unsafeGetDouble"); + test("unsafeGetObject"); + + test("unsafePutBoolean"); + test("unsafePutByte"); + test("unsafePutShort"); + test("unsafePutChar"); + test("unsafePutInt"); + test("unsafePutFloat"); + test("unsafePutDouble"); + test("unsafePutObject"); + + test("unsafeDirectMemoryRead"); + test("unsafeDirectMemoryWrite"); + + AtomicInteger a1 = new AtomicInteger(42); + AtomicInteger a2 = new AtomicInteger(42); + assertEquals(unsafe.compareAndSwapInt(a1, off(a1, "value"), 42, 53), compareAndSwapInt(unsafe, a2, off(a2, "value"), 42, 53)); + assertEquals(a1.get(), a2.get()); + + AtomicLong l1 = new AtomicLong(42); + AtomicLong l2 = new AtomicLong(42); + assertEquals(unsafe.compareAndSwapLong(l1, off(l1, "value"), 42, 53), compareAndSwapLong(unsafe, l2, off(l2, "value"), 42, 53)); + assertEquals(l1.get(), l2.get()); + + AtomicReference o1 = new AtomicReference<>("42"); + AtomicReference o2 = new AtomicReference<>("42"); + assertEquals(unsafe.compareAndSwapObject(o1, off(o1, "value"), "42", "53"), compareAndSwapObject(unsafe, o2, off(o2, "value"), "42", "53")); + assertEquals(o1.get(), o2.get()); + + Foo f1 = new Foo(); + f1.test("z", "Boolean", Boolean.TRUE); + f1.test("b", "Byte", Byte.MIN_VALUE); + f1.test("s", "Short", Short.MAX_VALUE); + f1.test("c", "Char", '!'); + f1.test("i", "Int", 1010010); + f1.test("f", "Float", -34.5F); + f1.test("l", "Long", 99999L); + f1.test("d", "Double", 1234.5678D); + f1.test("o", "Object", "object"); + } + + @SuppressWarnings("all") + public static boolean unsafeCompareAndSwapInt(Unsafe unsafe, Object obj, long offset) { + return unsafe.compareAndSwapInt(obj, offset, 0, 1); + } + + @SuppressWarnings("all") + public static boolean unsafeCompareAndSwapLong(Unsafe unsafe, Object obj, long offset) { + return unsafe.compareAndSwapLong(obj, offset, 0, 1); + } + + @SuppressWarnings("all") + public static boolean unsafeCompareAndSwapObject(Unsafe unsafe, Object obj, long offset) { + return unsafe.compareAndSwapObject(obj, offset, null, new Object()); + } + + @SuppressWarnings("all") + public static boolean unsafeGetBoolean(Unsafe unsafe, Object obj, long offset) { + return unsafe.getBoolean(obj, offset) && unsafe.getBooleanVolatile(obj, offset); + } + + @SuppressWarnings("all") + public static int unsafeGetByte(Unsafe unsafe, Object obj, long offset) { + return unsafe.getByte(obj, offset) + unsafe.getByteVolatile(obj, offset); + } + + @SuppressWarnings("all") + public static int unsafeGetShort(Unsafe unsafe, Object obj, long offset) { + return unsafe.getShort(obj, offset) + unsafe.getShortVolatile(obj, offset); + } + + @SuppressWarnings("all") + public static int unsafeGetChar(Unsafe unsafe, Object obj, long offset) { + return unsafe.getChar(obj, offset) + unsafe.getCharVolatile(obj, offset); + } + + @SuppressWarnings("all") + public static int unsafeGetInt(Unsafe unsafe, Object obj, long offset) { + return unsafe.getInt(obj, offset) + unsafe.getIntVolatile(obj, offset); + } + + @SuppressWarnings("all") + public static long unsafeGetLong(Unsafe unsafe, Object obj, long offset) { + return unsafe.getLong(obj, offset) + unsafe.getLongVolatile(obj, offset); + } + + @SuppressWarnings("all") + public static float unsafeGetFloat(Unsafe unsafe, Object obj, long offset) { + return unsafe.getFloat(obj, offset) + unsafe.getFloatVolatile(obj, offset); + } + + @SuppressWarnings("all") + public static double unsafeGetDouble(Unsafe unsafe, Object obj, long offset) { + return unsafe.getDouble(obj, offset) + unsafe.getDoubleVolatile(obj, offset); + } + + @SuppressWarnings("all") + public static boolean unsafeGetObject(Unsafe unsafe, Object obj, long offset) { + return unsafe.getObject(obj, offset) == unsafe.getObjectVolatile(obj, offset); + } + + @SuppressWarnings("all") + public static void unsafePutBoolean(Unsafe unsafe, Object obj, long offset, boolean value) { + unsafe.putBoolean(obj, offset, value); + unsafe.putBooleanVolatile(obj, offset, value); + } + + @SuppressWarnings("all") + public static void unsafePutByte(Unsafe unsafe, Object obj, long offset, byte value) { + unsafe.putByte(obj, offset, value); + unsafe.putByteVolatile(obj, offset, value); + } + + @SuppressWarnings("all") + public static void unsafePutShort(Unsafe unsafe, Object obj, long offset, short value) { + unsafe.putShort(obj, offset, value); + unsafe.putShortVolatile(obj, offset, value); + } + + @SuppressWarnings("all") + public static void unsafePutChar(Unsafe unsafe, Object obj, long offset, char value) { + unsafe.putChar(obj, offset, value); + unsafe.putCharVolatile(obj, offset, value); + } + + @SuppressWarnings("all") + public static void unsafePutInt(Unsafe unsafe, Object obj, long offset, int value) { + unsafe.putInt(obj, offset, value); + unsafe.putIntVolatile(obj, offset, value); + unsafe.putOrderedInt(obj, offset, value); + } + + @SuppressWarnings("all") + public static void unsafePutLong(Unsafe unsafe, Object obj, long offset, long value) { + unsafe.putLong(obj, offset, value); + unsafe.putLongVolatile(obj, offset, value); + unsafe.putOrderedLong(obj, offset, value); + } + + @SuppressWarnings("all") + public static void unsafePutFloat(Unsafe unsafe, Object obj, long offset, float value) { + unsafe.putFloat(obj, offset, value); + unsafe.putFloatVolatile(obj, offset, value); + } + + @SuppressWarnings("all") + public static void unsafePutDouble(Unsafe unsafe, Object obj, long offset, double value) { + unsafe.putDouble(obj, offset, value); + unsafe.putDoubleVolatile(obj, offset, value); + } + + @SuppressWarnings("all") + public static void unsafePutObject(Unsafe unsafe, Object obj, long offset, Object value) { + unsafe.putObject(obj, offset, value); + unsafe.putObjectVolatile(obj, offset, value); + unsafe.putOrderedObject(obj, offset, value); + } + + @SuppressWarnings("all") + public static double unsafeDirectMemoryRead(Unsafe unsafe, long address) { + // Unsafe.getBoolean(long) and Unsafe.getObject(long) do not exist + return unsafe.getByte(address) + unsafe.getShort(address) + unsafe.getChar(address) + unsafe.getInt(address) + unsafe.getLong(address) + unsafe.getFloat(address) + unsafe.getDouble(address); + } + + @SuppressWarnings("all") + public static void unsafeDirectMemoryWrite(Unsafe unsafe, long address, byte value) { + // Unsafe.putBoolean(long) and Unsafe.putObject(long) do not exist + unsafe.putByte(address, value); + unsafe.putShort(address, value); + unsafe.putChar(address, (char) value); + unsafe.putInt(address, value); + unsafe.putLong(address, value); + unsafe.putFloat(address, value); + unsafe.putDouble(address, value); + } + + @Test + public void testGetAndAddInt() throws Exception { + Foo f1 = new Foo(); + Foo f2 = new Foo(); + long offset = off(f1, "i"); + Class[] parameterTypes = new Class[]{Object.class, long.class, int.class}; + for (int delta = Integer.MAX_VALUE - 10; delta < Integer.MAX_VALUE; delta++) { + Object[] args1 = new Object[]{f1, offset, delta}; + Object[] args2 = new Object[]{f2, offset, delta}; + testSubstitution("getAndAddInt", Unsafe.class, "getAndAddInt", parameterTypes, unsafe, args1, args2); + } + } + + public static int getAndAddInt(Object obj, long offset, int delta) { + return unsafe.getAndAddInt(obj, offset, delta); + } + + @Test + public void testGetAndAddLong() throws Exception { + Foo f1 = new Foo(); + Foo f2 = new Foo(); + long offset = off(f1, "l"); + Class[] parameterTypes = new Class[]{Object.class, long.class, long.class}; + for (long delta = Long.MAX_VALUE - 10; delta < Long.MAX_VALUE; delta++) { + Object[] args1 = new Object[]{f1, offset, delta}; + Object[] args2 = new Object[]{f2, offset, delta}; + testSubstitution("getAndAddLong", Unsafe.class, "getAndAddLong", parameterTypes, unsafe, args1, args2); + } + } + + public static long getAndAddLong(Object obj, long offset, long delta) { + return unsafe.getAndAddLong(obj, offset, delta); + } + + @Test + public void testGetAndSetInt() throws Exception { + Foo f1 = new Foo(); + Foo f2 = new Foo(); + long offset = off(f1, "i"); + Class[] parameterTypes = new Class[]{Object.class, long.class, int.class}; + for (int delta = Integer.MAX_VALUE - 10; delta < Integer.MAX_VALUE; delta++) { + Object[] args1 = new Object[]{f1, offset, delta}; + Object[] args2 = new Object[]{f2, offset, delta}; + testSubstitution("getAndSetInt", Unsafe.class, "getAndSetInt", parameterTypes, unsafe, args1, args2); + } + } + + public static int getAndSetInt(Object obj, long offset, int newValue) { + return unsafe.getAndSetInt(obj, offset, newValue); + } + + @Test + public void testGetAndSetLong() throws Exception { + Foo f1 = new Foo(); + Foo f2 = new Foo(); + long offset = off(f1, "l"); + Class[] parameterTypes = new Class[]{Object.class, long.class, long.class}; + for (long newValue = Long.MAX_VALUE - 10; newValue < Long.MAX_VALUE; newValue++) { + Object[] args1 = new Object[]{f1, offset, newValue}; + Object[] args2 = new Object[]{f2, offset, newValue}; + testSubstitution("getAndSetLong", Unsafe.class, "getAndSetLong", parameterTypes, unsafe, args1, args2); + } + } + + public static long getAndSetLong(Object obj, long offset, long newValue) { + return unsafe.getAndSetLong(obj, offset, newValue); + } + + @Test + public void testGetAndSetObject() throws Exception { + Foo f1 = new Foo(); + Foo f2 = new Foo(); + long offset = off(f1, "o"); + Class[] parameterTypes = new Class[]{Object.class, long.class, Object.class}; + for (long i = 0; i < 10; i++) { + Object o = new Object(); + Object[] args1 = new Object[]{f1, offset, o}; + Object[] args2 = new Object[]{f2, offset, o}; + testSubstitution("getAndSetObject", Unsafe.class, "getAndSetObject", parameterTypes, unsafe, args1, args2); + System.gc(); + } + } + + public static Object getAndSetObject(Object obj, long offset, Object newValue) { + return unsafe.getAndSetObject(obj, offset, newValue); + } + +} diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/test/WordTest.java --- a/graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/test/WordTest.java Fri Apr 25 16:21:07 2014 +0200 +++ b/graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/test/WordTest.java Mon Apr 28 11:18:15 2014 +0200 @@ -24,6 +24,8 @@ import java.lang.reflect.*; +import org.junit.*; + import com.oracle.graal.api.code.*; import com.oracle.graal.api.meta.*; import com.oracle.graal.compiler.test.*; @@ -31,7 +33,6 @@ import com.oracle.graal.replacements.*; import com.oracle.graal.replacements.ReplacementsImpl.FrameStateProcessing; import com.oracle.graal.replacements.Snippet.SnippetInliningPolicy; -import com.oracle.graal.test.*; import com.oracle.graal.word.*; /** @@ -53,7 +54,7 @@ return installer.makeGraph(resolvedMethod, null, resolvedMethod, inliningPolicy.get(), FrameStateProcessing.CollapseFrameForSingleSideEffect); } - @LongTest + @Test public void construction() { long[] words = new long[]{Long.MIN_VALUE, Long.MIN_VALUE + 1, -1L, 0L, 1L, Long.MAX_VALUE - 1, Long.MAX_VALUE, Integer.MAX_VALUE - 1L, Integer.MAX_VALUE, Integer.MAX_VALUE + 1L, Integer.MIN_VALUE - 1L, Integer.MIN_VALUE, Integer.MIN_VALUE + 1L}; @@ -65,7 +66,7 @@ } } - @LongTest + @Test public void testArithmetic() { long[] words = new long[]{Long.MIN_VALUE, Long.MIN_VALUE + 1, -1L, 0L, 1L, Long.MAX_VALUE - 1, Long.MAX_VALUE, Integer.MAX_VALUE - 1L, Integer.MAX_VALUE, Integer.MAX_VALUE + 1L, Integer.MIN_VALUE - 1L, Integer.MIN_VALUE, Integer.MIN_VALUE + 1L}; @@ -102,7 +103,7 @@ } } - @LongTest + @Test public void testCompare() { long[] words = new long[]{Long.MIN_VALUE, Long.MIN_VALUE + 1, -1L, 0L, 1L, Long.MAX_VALUE - 1, Long.MAX_VALUE}; for (long word1 : words) { diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/BoxingSnippets.java --- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/BoxingSnippets.java Fri Apr 25 16:21:07 2014 +0200 +++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/BoxingSnippets.java Mon Apr 28 11:18:15 2014 +0200 @@ -22,22 +22,21 @@ */ package com.oracle.graal.replacements; -import static com.oracle.graal.phases.GraalOptions.*; +import static com.oracle.graal.compiler.common.GraalOptions.*; import static com.oracle.graal.replacements.SnippetTemplate.*; -import java.lang.reflect.*; import java.util.*; import com.oracle.graal.api.code.*; import com.oracle.graal.api.meta.*; import com.oracle.graal.api.replacements.*; +import com.oracle.graal.compiler.common.type.*; import com.oracle.graal.debug.*; import com.oracle.graal.graph.Node.NodeIntrinsic; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.calc.*; import com.oracle.graal.nodes.extended.*; import com.oracle.graal.nodes.spi.*; -import com.oracle.graal.nodes.type.*; import com.oracle.graal.nodes.util.*; import com.oracle.graal.phases.util.*; import com.oracle.graal.replacements.Snippet.Fold; @@ -57,7 +56,7 @@ @Override public boolean shouldInline(ResolvedJavaMethod method, ResolvedJavaMethod caller) { - if (Modifier.isNative(method.getModifiers())) { + if (method.isNative()) { return false; } if (method.getAnnotation(Fold.class) != null) { diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/CollapseFrameForSingleSideEffectPhase.java --- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/CollapseFrameForSingleSideEffectPhase.java Fri Apr 25 16:21:07 2014 +0200 +++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/CollapseFrameForSingleSideEffectPhase.java Mon Apr 28 11:18:15 2014 +0200 @@ -24,6 +24,7 @@ import java.util.*; +import com.oracle.graal.api.code.*; import com.oracle.graal.graph.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.util.*; @@ -33,12 +34,12 @@ import com.oracle.graal.phases.graph.ReentrantNodeIterator.NodeIteratorClosure; /** - * This phase ensures that there's a single {@linkplain FrameState#AFTER_BCI collapsed frame state} - * per path. + * This phase ensures that there's a single {@linkplain BytecodeFrame#AFTER_BCI collapsed frame + * state} per path. * * Removes other frame states from {@linkplain StateSplit#hasSideEffect() non-side-effecting} nodes - * in the graph, and replaces them with {@linkplain FrameState#INVALID_FRAMESTATE_BCI invalid frame - * states}. + * in the graph, and replaces them with {@linkplain BytecodeFrame#INVALID_FRAMESTATE_BCI invalid + * frame states}. * * The invalid frame states ensure that no deoptimization to a snippet frame state will happen. */ @@ -65,7 +66,7 @@ return new IterationState(this, sideEffect.asNode(), null, true); } - public IterationState addBranch(AbstractBeginNode begin) { + public IterationState addBranch(BeginNode begin) { return new IterationState(this, begin, null, this.invalid); } @@ -176,7 +177,7 @@ if (!unwindSideEffects.contains(returnSideEffect) && !maskedSideEffects.contains(returnSideEffect)) { StateSplit split = (StateSplit) returnSideEffect; if (split.stateAfter() != null) { - split.setStateAfter(graph.add(new FrameState(FrameState.AFTER_BCI))); + split.setStateAfter(graph.add(new FrameState(BytecodeFrame.AFTER_BCI))); } } } @@ -185,14 +186,14 @@ if (!returnSideEffects.contains(unwindSideEffect) && !maskedSideEffects.contains(unwindSideEffect)) { StateSplit split = (StateSplit) unwindSideEffect; if (split.stateAfter() != null) { - split.setStateAfter(graph.add(new FrameState(FrameState.AFTER_EXCEPTION_BCI))); + split.setStateAfter(graph.add(new FrameState(BytecodeFrame.AFTER_EXCEPTION_BCI))); } } } } @Override - protected IterationState afterSplit(AbstractBeginNode node, IterationState oldState) { + protected IterationState afterSplit(BeginNode node, IterationState oldState) { return oldState.addBranch(node); } @@ -214,7 +215,7 @@ } private static FrameState createInvalidFrameState(FixedNode node) { - return node.graph().add(new FrameState(FrameState.INVALID_FRAMESTATE_BCI)); + return node.graph().add(new FrameState(BytecodeFrame.INVALID_FRAMESTATE_BCI)); } } } diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/GraalMethodSubstitutions.java --- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/GraalMethodSubstitutions.java Fri Apr 25 16:21:07 2014 +0200 +++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/GraalMethodSubstitutions.java Mon Apr 28 11:18:15 2014 +0200 @@ -22,10 +22,11 @@ */ package com.oracle.graal.replacements; -import static com.oracle.graal.phases.GraalOptions.*; +import static com.oracle.graal.compiler.common.GraalOptions.*; import com.oracle.graal.api.code.*; import com.oracle.graal.api.meta.*; +import com.oracle.graal.api.replacements.*; import com.oracle.graal.api.runtime.*; import com.oracle.graal.nodes.spi.*; @@ -35,7 +36,7 @@ @ServiceProvider(ReplacementsProvider.class) public class GraalMethodSubstitutions implements ReplacementsProvider { - public void registerReplacements(MetaAccessProvider metaAccess, LoweringProvider loweringProvider, Replacements replacements, TargetDescription target) { + public void registerReplacements(MetaAccessProvider metaAccess, LoweringProvider loweringProvider, SnippetReflectionProvider snippetReflection, Replacements replacements, TargetDescription target) { for (Class clazz : BoxingSubstitutions.getClasses()) { replacements.registerSubstitutions(clazz); } diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/GraphKit.java --- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/GraphKit.java Fri Apr 25 16:21:07 2014 +0200 +++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/GraphKit.java Mon Apr 28 11:18:15 2014 +0200 @@ -96,7 +96,7 @@ } public InvokeNode createInvoke(Class declaringClass, String name, ValueNode... args) { - return createInvoke(declaringClass, name, InvokeKind.Static, null, FrameState.UNKNOWN_BCI, args); + return createInvoke(declaringClass, name, InvokeKind.Static, null, BytecodeFrame.UNKNOWN_BCI, args); } /** @@ -125,7 +125,7 @@ * arguments. */ public InvokeNode createInvoke(ResolvedJavaMethod method, InvokeKind invokeKind, HIRFrameStateBuilder frameStateBuilder, int bci, ValueNode... args) { - assert Modifier.isStatic(method.getModifiers()) == (invokeKind == InvokeKind.Static); + assert method.isStatic() == (invokeKind == InvokeKind.Static); Signature signature = method.getSignature(); JavaType returnType = signature.getReturnType(null); assert checkArgs(method, args); @@ -157,7 +157,7 @@ */ public boolean checkArgs(ResolvedJavaMethod method, ValueNode... args) { Signature signature = method.getSignature(); - boolean isStatic = Modifier.isStatic(method.getModifiers()); + boolean isStatic = method.isStatic(); if (signature.getParameterCount(!isStatic) != args.length) { throw new AssertionError(graph + ": wrong number of arguments to " + method); } diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/InstanceOfSnippetsTemplates.java --- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/InstanceOfSnippetsTemplates.java Fri Apr 25 16:21:07 2014 +0200 +++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/InstanceOfSnippetsTemplates.java Mon Apr 28 11:18:15 2014 +0200 @@ -28,6 +28,7 @@ import com.oracle.graal.api.code.*; import com.oracle.graal.api.replacements.*; +import com.oracle.graal.compiler.common.calc.*; import com.oracle.graal.graph.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.calc.*; diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/NodeIntrinsificationPhase.java --- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/NodeIntrinsificationPhase.java Fri Apr 25 16:21:07 2014 +0200 +++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/NodeIntrinsificationPhase.java Mon Apr 28 11:18:15 2014 +0200 @@ -30,6 +30,8 @@ import com.oracle.graal.api.code.*; import com.oracle.graal.api.meta.*; import com.oracle.graal.api.replacements.*; +import com.oracle.graal.compiler.common.*; +import com.oracle.graal.compiler.common.type.*; import com.oracle.graal.debug.*; import com.oracle.graal.debug.internal.*; import com.oracle.graal.graph.*; @@ -40,7 +42,6 @@ import com.oracle.graal.nodes.calc.*; import com.oracle.graal.nodes.extended.*; import com.oracle.graal.nodes.java.*; -import com.oracle.graal.nodes.type.*; import com.oracle.graal.nodes.util.*; import com.oracle.graal.phases.*; import com.oracle.graal.phases.util.*; @@ -80,7 +81,7 @@ NodeIntrinsic intrinsic = getIntrinsic(target); if (intrinsic != null) { assert target.getAnnotation(Fold.class) == null; - assert Modifier.isStatic(target.getModifiers()) : "node intrinsic must be static: " + target; + assert target.isStatic() : "node intrinsic must be static: " + target; ResolvedJavaType[] parameterTypes = resolveJavaTypes(signatureToTypes(target), declaringClass); diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/NodeIntrinsificationVerificationPhase.java --- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/NodeIntrinsificationVerificationPhase.java Fri Apr 25 16:21:07 2014 +0200 +++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/NodeIntrinsificationVerificationPhase.java Mon Apr 28 11:18:15 2014 +0200 @@ -23,6 +23,7 @@ package com.oracle.graal.replacements; import com.oracle.graal.api.meta.*; +import com.oracle.graal.compiler.common.*; import com.oracle.graal.graph.*; import com.oracle.graal.graph.Node.ConstantNodeParameter; import com.oracle.graal.graph.Node.NodeIntrinsic; diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/ReplacementsImpl.java --- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/ReplacementsImpl.java Fri Apr 25 16:21:07 2014 +0200 +++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/ReplacementsImpl.java Mon Apr 28 11:18:15 2014 +0200 @@ -24,7 +24,7 @@ import static com.oracle.graal.api.meta.MetaUtil.*; import static com.oracle.graal.compiler.GraalCompiler.*; -import static com.oracle.graal.phases.GraalOptions.*; +import static com.oracle.graal.compiler.common.GraalOptions.*; import java.lang.reflect.*; import java.util.*; @@ -35,6 +35,7 @@ import com.oracle.graal.api.code.*; import com.oracle.graal.api.meta.*; import com.oracle.graal.api.replacements.*; +import com.oracle.graal.compiler.common.*; import com.oracle.graal.debug.*; import com.oracle.graal.debug.Debug.Scope; import com.oracle.graal.debug.internal.*; @@ -95,7 +96,7 @@ @Override public StructuredGraph getSnippet(ResolvedJavaMethod method, ResolvedJavaMethod recursiveEntry) { assert method.getAnnotation(Snippet.class) != null : "Snippet must be annotated with @" + Snippet.class.getSimpleName(); - assert !Modifier.isAbstract(method.getModifiers()) && !Modifier.isNative(method.getModifiers()) : "Snippet must not be abstract or native"; + assert !method.isAbstract() && !method.isNative() : "Snippet must not be abstract or native"; StructuredGraph graph = UseSnippetGraphCache ? graphs.get(method) : null; if (graph == null) { @@ -531,7 +532,7 @@ } private static boolean isInlinable(final ResolvedJavaMethod method) { - return !Modifier.isAbstract(method.getModifiers()) && !Modifier.isNative(method.getModifiers()); + return !method.isAbstract() && !method.isNative(); } private static String originalName(Method substituteMethod, String methodSubstitution) { diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/Snippet.java --- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/Snippet.java Fri Apr 25 16:21:07 2014 +0200 +++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/Snippet.java Mon Apr 28 11:18:15 2014 +0200 @@ -23,8 +23,6 @@ package com.oracle.graal.replacements; import java.lang.annotation.*; -import java.lang.reflect.*; - import com.oracle.graal.api.meta.*; import com.oracle.graal.graph.Node.NodeIntrinsic; import com.oracle.graal.replacements.nodes.*; @@ -89,7 +87,7 @@ @Override public boolean shouldInline(ResolvedJavaMethod method, ResolvedJavaMethod caller) { - if (Modifier.isNative(method.getModifiers())) { + if (method.isNative()) { return false; } if (method.getAnnotation(Fold.class) != null) { diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/SnippetCounter.java --- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/SnippetCounter.java Fri Apr 25 16:21:07 2014 +0200 +++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/SnippetCounter.java Mon Apr 28 11:18:15 2014 +0200 @@ -24,23 +24,21 @@ //JaCoCo Exclude -import static com.oracle.graal.graph.UnsafeAccess.*; +import static com.oracle.graal.compiler.common.UnsafeAccess.*; import java.io.*; import java.util.*; import com.oracle.graal.api.meta.*; -import com.oracle.graal.graph.*; +import com.oracle.graal.compiler.common.*; import com.oracle.graal.replacements.Snippet.Fold; -import com.oracle.graal.replacements.nodes.*; +import com.oracle.graal.word.*; /** * A counter that can be safely {@linkplain #inc() incremented} from within a snippet for gathering * snippet specific metrics. */ public class SnippetCounter implements Comparable { - private static final LocationIdentity SNIPPET_COUNTER_LOCATION = new NamedLocationIdentity("SnippetCounter"); - /** * A group of related counters. */ @@ -107,7 +105,7 @@ /** * Creates a counter. - * + * * @param group the group to which the counter belongs. If this is null, the newly created * counter is disabled and {@linkplain #inc() incrementing} is a no-op. * @param name the name of the counter @@ -130,12 +128,20 @@ } /** + * We do not want to use the {@link LocationIdentity} of the {@link #value} field, so that the + * usage in snippets is always possible. If a method accesses the counter via the field and the + * snippet, the result might not be correct though. + */ + protected static final LocationIdentity SNIPPET_COUNTER_LOCATION = new NamedLocationIdentity("SnippetCounter"); + + /** * Increments the value of this counter. This method can be safely used in a snippet if it is * invoked on a compile-time constant {@link SnippetCounter} object. */ public void inc() { if (group != null) { - DirectObjectStoreNode.storeLong(this, countOffset(), 0, value + 1, SNIPPET_COUNTER_LOCATION); + long loadedValue = ObjectAccess.readLong(this, countOffset(), SNIPPET_COUNTER_LOCATION); + ObjectAccess.writeLong(this, countOffset(), loadedValue + 1, SNIPPET_COUNTER_LOCATION); } } diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/SnippetTemplate.java --- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/SnippetTemplate.java Fri Apr 25 16:21:07 2014 +0200 +++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/SnippetTemplate.java Mon Apr 28 11:18:15 2014 +0200 @@ -23,9 +23,11 @@ package com.oracle.graal.replacements; import static com.oracle.graal.api.meta.LocationIdentity.*; + import static com.oracle.graal.api.meta.MetaUtil.*; import static com.oracle.graal.debug.Debug.*; import static java.util.FormattableFlags.*; +import static com.oracle.graal.compiler.common.GraalOptions.*; import java.io.*; import java.lang.reflect.*; @@ -35,11 +37,13 @@ import com.oracle.graal.api.code.*; import com.oracle.graal.api.meta.*; import com.oracle.graal.api.replacements.*; +import com.oracle.graal.compiler.common.*; +import com.oracle.graal.compiler.common.type.*; import com.oracle.graal.debug.*; import com.oracle.graal.debug.Debug.Scope; import com.oracle.graal.debug.internal.*; +import com.oracle.graal.graph.Graph.Mark; import com.oracle.graal.graph.*; -import com.oracle.graal.graph.Graph.Mark; import com.oracle.graal.loop.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.StructuredGraph.GuardsStage; @@ -47,7 +51,6 @@ import com.oracle.graal.nodes.extended.*; import com.oracle.graal.nodes.java.*; import com.oracle.graal.nodes.spi.*; -import com.oracle.graal.nodes.type.*; import com.oracle.graal.nodes.util.*; import com.oracle.graal.phases.common.*; import com.oracle.graal.phases.common.FloatingReadPhase.MemoryMapImpl; @@ -101,7 +104,7 @@ this.method = method; instantiationCounter = Debug.metric("SnippetInstantiationCount[%s]", method); instantiationTimer = Debug.timer("SnippetInstantiationTime[%s]", method); - assert Modifier.isStatic(method.getModifiers()) : "snippet method must be static: " + MetaUtil.format("%H.%n", method); + assert method.isStatic() : "snippet method must be static: " + MetaUtil.format("%H.%n", method); int count = method.getSignature().getParameterCount(false); constantParameters = new boolean[count]; varargsParameters = new boolean[count]; @@ -964,7 +967,15 @@ * if no FloatingReadNode is reading from this location, the kill to this location is fine. */ for (FloatingReadNode frn : replacee.graph().getNodes(FloatingReadNode.class)) { - assert !(kills.contains(frn.location().getLocationIdentity())) : frn + " reads from " + frn.location().getLocationIdentity() + " but " + replacee + " does not kill this location"; + LocationIdentity locationIdentity = frn.location().getLocationIdentity(); + if (SnippetCounters.getValue()) { + // accesses to snippet counters are artificially introduced and violate the memory + // semantics. + if (locationIdentity == SnippetCounter.SNIPPET_COUNTER_LOCATION) { + continue; + } + } + assert !kills.contains(locationIdentity) : frn + " reads from location \"" + locationIdentity + "\" but " + replacee + " does not kill this location"; } return true; } diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/StringSubstitutions.java --- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/StringSubstitutions.java Fri Apr 25 16:21:07 2014 +0200 +++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/StringSubstitutions.java Mon Apr 28 11:18:15 2014 +0200 @@ -22,12 +22,12 @@ */ package com.oracle.graal.replacements; -import static com.oracle.graal.graph.UnsafeAccess.*; +import static com.oracle.graal.compiler.common.UnsafeAccess.*; import java.lang.reflect.*; import com.oracle.graal.api.replacements.*; -import com.oracle.graal.graph.*; +import com.oracle.graal.compiler.common.*; import com.oracle.graal.replacements.nodes.*; import edu.umd.cs.findbugs.annotations.*; diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/UnsafeSubstitutions.java --- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/UnsafeSubstitutions.java Fri Apr 25 16:21:07 2014 +0200 +++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/UnsafeSubstitutions.java Mon Apr 28 11:18:15 2014 +0200 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 2014, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -42,17 +42,17 @@ @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, Kind.Object); + return CompareAndSwapNode.compareAndSwap(o, 0, offset, expected, x, Kind.Object, LocationIdentity.ANY_LOCATION); } @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, Kind.Int); + return CompareAndSwapNode.compareAndSwap(o, 0, offset, expected, x, Kind.Int, LocationIdentity.ANY_LOCATION); } @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, Kind.Long); + return CompareAndSwapNode.compareAndSwap(o, 0, offset, expected, x, Kind.Long, LocationIdentity.ANY_LOCATION); } @MethodSubstitution(isStatic = false) @@ -399,4 +399,47 @@ } return DynamicNewInstanceNode.allocateInstance(clazz, true); } + + /** + * Guard for {@link Unsafe#getAndSetInt} method family. + */ + public static class GetAndSetGuard implements SubstitutionGuard { + public boolean execute() { + // FIXME should return whether the current compilation target supports these + String arch = System.getProperty("os.arch"); + switch (arch) { + case "amd64": + case "x86_64": + return true; + default: + return false; + } + } + } + + @MethodSubstitution(isStatic = false, guard = GetAndSetGuard.class) + public static int getAndAddInt(@SuppressWarnings("unused") final Object thisObj, Object o, long offset, int delta) { + return AtomicReadAndAddNode.getAndAddInt(o, offset, delta, LocationIdentity.ANY_LOCATION); + } + + @MethodSubstitution(isStatic = false, guard = GetAndSetGuard.class) + public static long getAndAddLong(@SuppressWarnings("unused") final Object thisObj, Object o, long offset, long delta) { + return AtomicReadAndAddNode.getAndAddLong(o, offset, delta, LocationIdentity.ANY_LOCATION); + } + + @MethodSubstitution(isStatic = false, guard = GetAndSetGuard.class) + public static int getAndSetInt(@SuppressWarnings("unused") final Object thisObj, Object o, long offset, int newValue) { + return AtomicReadAndWriteNode.getAndSetInt(o, offset, newValue, Kind.Int, LocationIdentity.ANY_LOCATION); + } + + @MethodSubstitution(isStatic = false, guard = GetAndSetGuard.class) + public static long getAndSetLong(@SuppressWarnings("unused") final Object thisObj, Object o, long offset, long newValue) { + return AtomicReadAndWriteNode.getAndSetLong(o, offset, newValue, Kind.Long, LocationIdentity.ANY_LOCATION); + } + + @MethodSubstitution(isStatic = false, guard = GetAndSetGuard.class) + public static Object getAndSetObject(@SuppressWarnings("unused") final Object thisObj, Object o, long offset, Object newValue) { + return AtomicReadAndWriteNode.getAndSetObject(o, offset, newValue, Kind.Object, LocationIdentity.ANY_LOCATION); + } + } diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/UnsignedMathSubstitutions.java --- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/UnsignedMathSubstitutions.java Fri Apr 25 16:21:07 2014 +0200 +++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/UnsignedMathSubstitutions.java Mon Apr 28 11:18:15 2014 +0200 @@ -22,7 +22,7 @@ */ package com.oracle.graal.replacements; -import static com.oracle.graal.nodes.calc.Condition.*; +import static com.oracle.graal.compiler.common.calc.Condition.*; import static com.oracle.graal.nodes.calc.ConditionalNode.*; import com.oracle.graal.api.code.*; diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/ArrayEqualsNode.java --- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/ArrayEqualsNode.java Fri Apr 25 16:21:07 2014 +0200 +++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/ArrayEqualsNode.java Mon Apr 28 11:18:15 2014 +0200 @@ -23,20 +23,18 @@ package com.oracle.graal.replacements.nodes; import com.oracle.graal.api.meta.*; -import com.oracle.graal.compiler.gen.*; -import com.oracle.graal.compiler.target.*; +import com.oracle.graal.compiler.common.type.*; import com.oracle.graal.graph.*; import com.oracle.graal.graph.spi.*; import com.oracle.graal.lir.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.spi.*; -import com.oracle.graal.nodes.type.*; import com.oracle.graal.nodes.util.*; /** * Compares two arrays with the same length. */ -public class ArrayEqualsNode extends FixedWithNextNode implements LIRGenLowerable, Canonicalizable, Virtualizable { +public class ArrayEqualsNode extends FixedWithNextNode implements LIRLowerable, Canonicalizable, Virtualizable { /** {@link Kind} of the arrays to compare. */ private final Kind kind; @@ -131,7 +129,7 @@ public static native boolean equals(double[] array1, double[] array2, int length); @Override - public void generate(NodeLIRBuilder gen) { + public void generate(NodeLIRBuilderTool gen) { Variable result = gen.newVariable(Kind.Int); gen.emitArrayEquals(kind, result, gen.operand(array1), gen.operand(array2), gen.operand(length)); gen.setResult(this, result); diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/BitCountNode.java --- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/BitCountNode.java Fri Apr 25 16:21:07 2014 +0200 +++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/BitCountNode.java Mon Apr 28 11:18:15 2014 +0200 @@ -23,16 +23,15 @@ package com.oracle.graal.replacements.nodes; import com.oracle.graal.api.meta.*; -import com.oracle.graal.compiler.gen.*; -import com.oracle.graal.compiler.target.*; +import com.oracle.graal.compiler.common.type.*; import com.oracle.graal.graph.*; import com.oracle.graal.graph.spi.*; import com.oracle.graal.lir.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.calc.*; -import com.oracle.graal.nodes.type.*; +import com.oracle.graal.nodes.spi.*; -public class BitCountNode extends FloatingNode implements LIRGenLowerable, Canonicalizable { +public class BitCountNode extends FloatingNode implements LIRLowerable, Canonicalizable { @Input private ValueNode value; @@ -65,7 +64,7 @@ } @Override - public void generate(NodeLIRBuilder gen) { + public void generate(NodeLIRBuilderTool gen) { Variable result = gen.newVariable(Kind.Int); gen.emitBitCount(result, gen.operand(value)); gen.setResult(this, result); diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/BitScanForwardNode.java --- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/BitScanForwardNode.java Fri Apr 25 16:21:07 2014 +0200 +++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/BitScanForwardNode.java Mon Apr 28 11:18:15 2014 +0200 @@ -23,16 +23,15 @@ package com.oracle.graal.replacements.nodes; import com.oracle.graal.api.meta.*; -import com.oracle.graal.compiler.gen.*; -import com.oracle.graal.compiler.target.*; +import com.oracle.graal.compiler.common.type.*; import com.oracle.graal.graph.*; import com.oracle.graal.graph.spi.*; import com.oracle.graal.lir.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.calc.*; -import com.oracle.graal.nodes.type.*; +import com.oracle.graal.nodes.spi.*; -public class BitScanForwardNode extends FloatingNode implements LIRGenLowerable, Canonicalizable { +public class BitScanForwardNode extends FloatingNode implements LIRLowerable, Canonicalizable { @Input private ValueNode value; @@ -72,7 +71,7 @@ } @Override - public void generate(NodeLIRBuilder gen) { + public void generate(NodeLIRBuilderTool gen) { Variable result = gen.newVariable(Kind.Int); gen.emitBitScanForward(result, gen.operand(value)); gen.setResult(this, result); diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/BitScanReverseNode.java --- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/BitScanReverseNode.java Fri Apr 25 16:21:07 2014 +0200 +++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/BitScanReverseNode.java Mon Apr 28 11:18:15 2014 +0200 @@ -23,16 +23,15 @@ package com.oracle.graal.replacements.nodes; import com.oracle.graal.api.meta.*; -import com.oracle.graal.compiler.gen.*; -import com.oracle.graal.compiler.target.*; +import com.oracle.graal.compiler.common.type.*; import com.oracle.graal.graph.*; import com.oracle.graal.graph.spi.*; import com.oracle.graal.lir.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.calc.*; -import com.oracle.graal.nodes.type.*; +import com.oracle.graal.nodes.spi.*; -public class BitScanReverseNode extends FloatingNode implements LIRGenLowerable, Canonicalizable { +public class BitScanReverseNode extends FloatingNode implements LIRLowerable, Canonicalizable { @Input private ValueNode value; @@ -79,7 +78,7 @@ } @Override - public void generate(NodeLIRBuilder gen) { + public void generate(NodeLIRBuilderTool gen) { Variable result = gen.newVariable(Kind.Int); gen.getLIRGeneratorTool().emitBitScanReverse(result, gen.operand(value)); gen.setResult(this, result); diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/DirectObjectStoreNode.java --- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/DirectObjectStoreNode.java Fri Apr 25 16:21:07 2014 +0200 +++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/DirectObjectStoreNode.java Mon Apr 28 11:18:15 2014 +0200 @@ -23,11 +23,11 @@ package com.oracle.graal.replacements.nodes; import com.oracle.graal.api.meta.*; +import com.oracle.graal.compiler.common.type.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.HeapAccess.BarrierType; import com.oracle.graal.nodes.extended.*; import com.oracle.graal.nodes.spi.*; -import com.oracle.graal.nodes.type.*; /** * A special purpose store node that differs from {@link UnsafeStoreNode} in that it is not a diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/DirectReadNode.java --- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/DirectReadNode.java Fri Apr 25 16:21:07 2014 +0200 +++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/DirectReadNode.java Mon Apr 28 11:18:15 2014 +0200 @@ -22,13 +22,13 @@ */ package com.oracle.graal.replacements.nodes; -import static com.oracle.graal.graph.UnsafeAccess.*; +import static com.oracle.graal.compiler.common.UnsafeAccess.*; import com.oracle.graal.api.meta.*; +import com.oracle.graal.compiler.common.type.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.extended.*; import com.oracle.graal.nodes.spi.*; -import com.oracle.graal.nodes.type.*; /** * A special purpose store node that differs from {@link UnsafeStoreNode} in that it is not a diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/DirectStoreNode.java --- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/DirectStoreNode.java Fri Apr 25 16:21:07 2014 +0200 +++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/DirectStoreNode.java Mon Apr 28 11:18:15 2014 +0200 @@ -22,13 +22,13 @@ */ package com.oracle.graal.replacements.nodes; -import static com.oracle.graal.graph.UnsafeAccess.*; +import static com.oracle.graal.compiler.common.UnsafeAccess.*; import com.oracle.graal.api.meta.*; +import com.oracle.graal.compiler.common.type.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.extended.*; import com.oracle.graal.nodes.spi.*; -import com.oracle.graal.nodes.type.*; /** * A special purpose store node that differs from {@link UnsafeStoreNode} in that it is not a diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/ExplodeLoopNode.java --- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/ExplodeLoopNode.java Fri Apr 25 16:21:07 2014 +0200 +++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/ExplodeLoopNode.java Mon Apr 28 11:18:15 2014 +0200 @@ -24,9 +24,9 @@ import java.util.*; +import com.oracle.graal.compiler.common.type.*; import com.oracle.graal.graph.*; import com.oracle.graal.nodes.*; -import com.oracle.graal.nodes.type.*; import com.oracle.graal.replacements.Snippet.VarargsParameter; /** diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/LoadSnippetVarargParameterNode.java --- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/LoadSnippetVarargParameterNode.java Fri Apr 25 16:21:07 2014 +0200 +++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/LoadSnippetVarargParameterNode.java Mon Apr 28 11:18:15 2014 +0200 @@ -22,10 +22,10 @@ */ package com.oracle.graal.replacements.nodes; +import com.oracle.graal.compiler.common.type.*; import com.oracle.graal.graph.*; import com.oracle.graal.graph.spi.*; import com.oracle.graal.nodes.*; -import com.oracle.graal.nodes.type.*; import com.oracle.graal.replacements.Snippet.VarargsParameter; /** diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/MacroNode.java --- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/MacroNode.java Fri Apr 25 16:21:07 2014 +0200 +++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/MacroNode.java Mon Apr 28 11:18:15 2014 +0200 @@ -22,9 +22,9 @@ */ package com.oracle.graal.replacements.nodes; -import static java.lang.reflect.Modifier.*; - +import com.oracle.graal.api.code.*; import com.oracle.graal.api.meta.*; +import com.oracle.graal.compiler.common.*; import com.oracle.graal.debug.*; import com.oracle.graal.debug.Debug.Scope; import com.oracle.graal.graph.*; @@ -88,7 +88,7 @@ StructuredGraph methodSubstitution = tool.getReplacements().getMethodSubstitution(getTargetMethod()); if (methodSubstitution != null) { methodSubstitution = methodSubstitution.copy(); - if (stateAfter() == null || stateAfter().bci == FrameState.AFTER_BCI) { + if (stateAfter() == null || stateAfter().bci == BytecodeFrame.AFTER_BCI) { /* * handles the case of a MacroNode inside a snippet used for another MacroNode * lowering @@ -135,7 +135,7 @@ if (replacementGraph != null) { // Pull out the receiver null check so that a replaced // receiver can be lowered if necessary - if (!isStatic(targetMethod.getModifiers())) { + if (!targetMethod.isStatic()) { ValueNode nonNullReceiver = InliningUtil.nonNullReceiver(invoke); if (nonNullReceiver instanceof Lowerable) { ((Lowerable) nonNullReceiver).lower(tool); @@ -172,7 +172,7 @@ if (!call.targetMethod().equals(getTargetMethod())) { throw new GraalInternalError("unexpected invoke %s in snippet", getClass().getSimpleName()); } - assert invoke.stateAfter().bci == FrameState.AFTER_BCI; + assert invoke.stateAfter().bci == BytecodeFrame.AFTER_BCI; // Here we need to fix the bci of the invoke InvokeNode newInvoke = snippetGraph.add(new InvokeNode(invoke.callTarget(), getBci())); newInvoke.setStateAfter(invoke.stateAfter()); diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/MathIntrinsicNode.java --- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/MathIntrinsicNode.java Fri Apr 25 16:21:07 2014 +0200 +++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/MathIntrinsicNode.java Mon Apr 28 11:18:15 2014 +0200 @@ -23,12 +23,14 @@ package com.oracle.graal.replacements.nodes; import com.oracle.graal.api.meta.*; +import com.oracle.graal.compiler.common.*; +import com.oracle.graal.compiler.common.type.*; import com.oracle.graal.graph.*; import com.oracle.graal.graph.spi.*; +import com.oracle.graal.lir.gen.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.calc.*; import com.oracle.graal.nodes.spi.*; -import com.oracle.graal.nodes.type.*; public class MathIntrinsicNode extends FloatingNode implements Canonicalizable, ArithmeticLIRLowerable { @@ -61,35 +63,35 @@ } @Override - public void generate(NodeLIRBuilderTool gen) { - Value input = gen.operand(x()); + public void generate(NodeMappableLIRBuilder builder, ArithmeticLIRGenerator gen) { + Value input = builder.operand(x()); Value result; switch (operation()) { case ABS: - result = gen.getLIRGeneratorTool().emitMathAbs(input); + result = gen.emitMathAbs(input); break; case SQRT: - result = gen.getLIRGeneratorTool().emitMathSqrt(input); + result = gen.emitMathSqrt(input); break; case LOG: - result = gen.getLIRGeneratorTool().emitMathLog(input, false); + result = gen.emitMathLog(input, false); break; case LOG10: - result = gen.getLIRGeneratorTool().emitMathLog(input, true); + result = gen.emitMathLog(input, true); break; case SIN: - result = gen.getLIRGeneratorTool().emitMathSin(input); + result = gen.emitMathSin(input); break; case COS: - result = gen.getLIRGeneratorTool().emitMathCos(input); + result = gen.emitMathCos(input); break; case TAN: - result = gen.getLIRGeneratorTool().emitMathTan(input); + result = gen.emitMathTan(input); break; default: throw GraalInternalError.shouldNotReachHere(); } - gen.setResult(this, result); + builder.setResult(this, result); } public Constant evalConst(Constant... inputs) { diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/MemoryAnchorNode.java --- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/MemoryAnchorNode.java Fri Apr 25 16:21:07 2014 +0200 +++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/MemoryAnchorNode.java Mon Apr 28 11:18:15 2014 +0200 @@ -22,14 +22,15 @@ */ package com.oracle.graal.replacements.nodes; +import com.oracle.graal.compiler.common.type.*; import com.oracle.graal.graph.*; +import com.oracle.graal.graph.spi.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.extended.*; import com.oracle.graal.nodes.spi.*; -import com.oracle.graal.nodes.type.*; @NodeInfo(allowedUsageTypes = {InputType.Memory}) -public class MemoryAnchorNode extends FixedWithNextNode implements LIRLowerable, MemoryNode { +public class MemoryAnchorNode extends FixedWithNextNode implements LIRLowerable, MemoryNode, Canonicalizable { public MemoryAnchorNode() { super(StampFactory.forVoid()); @@ -39,6 +40,11 @@ // Nothing to emit, since this node is used for structural purposes only. } + @Override + public Node canonical(CanonicalizerTool tool) { + return usages().isEmpty() ? null : this; + } + public MemoryCheckpoint asMemoryCheckpoint() { return null; } diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/ReadRegisterNode.java --- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/ReadRegisterNode.java Fri Apr 25 16:21:07 2014 +0200 +++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/ReadRegisterNode.java Mon Apr 28 11:18:15 2014 +0200 @@ -24,10 +24,10 @@ import com.oracle.graal.api.code.*; import com.oracle.graal.api.meta.*; +import com.oracle.graal.compiler.common.type.*; import com.oracle.graal.graph.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.spi.*; -import com.oracle.graal.nodes.type.*; /** * Access the value of a specific register. diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/ReverseBytesNode.java --- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/ReverseBytesNode.java Fri Apr 25 16:21:07 2014 +0200 +++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/ReverseBytesNode.java Mon Apr 28 11:18:15 2014 +0200 @@ -23,16 +23,15 @@ package com.oracle.graal.replacements.nodes; import com.oracle.graal.api.meta.*; -import com.oracle.graal.compiler.gen.*; -import com.oracle.graal.compiler.target.*; +import com.oracle.graal.compiler.common.type.*; import com.oracle.graal.graph.*; import com.oracle.graal.graph.spi.*; import com.oracle.graal.lir.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.calc.*; -import com.oracle.graal.nodes.type.*; +import com.oracle.graal.nodes.spi.*; -public class ReverseBytesNode extends FloatingNode implements LIRGenLowerable, Canonicalizable { +public class ReverseBytesNode extends FloatingNode implements LIRLowerable, Canonicalizable { @Input private ValueNode value; @@ -66,9 +65,9 @@ } @Override - public void generate(NodeLIRBuilder gen) { + public void generate(NodeLIRBuilderTool gen) { Variable result = gen.newVariable(value.getKind()); - gen.getLIRGenerator().emitByteSwap(result, gen.operand(value)); + gen.getLIRGeneratorTool().emitByteSwap(result, gen.operand(value)); gen.setResult(this, result); } } diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/WriteRegisterNode.java --- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/WriteRegisterNode.java Fri Apr 25 16:21:07 2014 +0200 +++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/WriteRegisterNode.java Mon Apr 28 11:18:15 2014 +0200 @@ -24,10 +24,10 @@ import com.oracle.graal.api.code.*; import com.oracle.graal.api.meta.*; +import com.oracle.graal.compiler.common.type.*; import com.oracle.graal.graph.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.spi.*; -import com.oracle.graal.nodes.type.*; /** * Changes the value of a specific register. diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.sparc/src/com/oracle/graal/sparc/SPARC.java --- a/graal/com.oracle.graal.sparc/src/com/oracle/graal/sparc/SPARC.java Fri Apr 25 16:21:07 2014 +0200 +++ b/graal/com.oracle.graal.sparc/src/com/oracle/graal/sparc/SPARC.java Mon Apr 28 11:18:15 2014 +0200 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2009, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 2014, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -35,28 +35,28 @@ */ public class SPARC extends Architecture { - // @formatter:off - public static final RegisterCategory CPU = new RegisterCategory("CPU"); public static final RegisterCategory FPU = new RegisterCategory("FPU"); // General purpose registers - public static final Register r0 = new Register(0, 0, "g0", CPU); - public static final Register r1 = new Register(1, 1, "g1", CPU); - public static final Register r2 = new Register(2, 2, "g2", CPU); - public static final Register r3 = new Register(3, 3, "g3", CPU); - public static final Register r4 = new Register(4, 4, "g4", CPU); - public static final Register r5 = new Register(5, 5, "g5", CPU); - public static final Register r6 = new Register(6, 6, "g6", CPU); - public static final Register r7 = new Register(7, 7, "g7", CPU); - public static final Register r8 = new Register(8, 8, "o0", CPU); - public static final Register r9 = new Register(9, 9, "o1", CPU); + public static final Register r0 = new Register(0, 0, "g0", CPU); + public static final Register r1 = new Register(1, 1, "g1", CPU); + public static final Register r2 = new Register(2, 2, "g2", CPU); + public static final Register r3 = new Register(3, 3, "g3", CPU); + public static final Register r4 = new Register(4, 4, "g4", CPU); + public static final Register r5 = new Register(5, 5, "g5", CPU); + public static final Register r6 = new Register(6, 6, "g6", CPU); + public static final Register r7 = new Register(7, 7, "g7", CPU); + + public static final Register r8 = new Register(8, 8, "o0", CPU); + public static final Register r9 = new Register(9, 9, "o1", CPU); public static final Register r10 = new Register(10, 10, "o2", CPU); public static final Register r11 = new Register(11, 11, "o3", CPU); public static final Register r12 = new Register(12, 12, "o4", CPU); public static final Register r13 = new Register(13, 13, "o5", CPU); public static final Register r14 = new Register(14, 14, "o6", CPU); public static final Register r15 = new Register(15, 15, "o7", CPU); + public static final Register r16 = new Register(16, 16, "l0", CPU); public static final Register r17 = new Register(17, 17, "l1", CPU); public static final Register r18 = new Register(18, 18, "l2", CPU); @@ -65,6 +65,7 @@ public static final Register r21 = new Register(21, 21, "l5", CPU); public static final Register r22 = new Register(22, 22, "l6", CPU); public static final Register r23 = new Register(23, 23, "l7", CPU); + public static final Register r24 = new Register(24, 24, "i0", CPU); public static final Register r25 = new Register(25, 25, "i1", CPU); public static final Register r26 = new Register(26, 26, "i2", CPU); @@ -113,12 +114,14 @@ public static final Register sp = o6; public static final Register fp = i6; + // @formatter:off public static final Register[] cpuRegisters = { r0, r1, r2, r3, r4, r5, r6, r7, r8, r9, r10, r11, r12, r13, r14, r15, r16, r17, r18, r19, r20, r21, r22, r23, r24, r25, r26, r27, r28, r29, r30, r31 }; + // @formatter:on // Floating point registers public static final Register f0 = new Register(32, 0, "f0", FPU); @@ -130,6 +133,43 @@ public static final Register f6 = new Register(38, 6, "f6", FPU); public static final Register f7 = new Register(39, 7, "f7", FPU); + public static final Register f8 = new Register(40, 8, "f8", FPU); + public static final Register f9 = new Register(41, 9, "f9", FPU); + public static final Register f10 = new Register(42, 10, "f10", FPU); + public static final Register f11 = new Register(43, 11, "f11", FPU); + public static final Register f12 = new Register(44, 12, "f12", FPU); + public static final Register f13 = new Register(45, 13, "f13", FPU); + public static final Register f14 = new Register(46, 14, "f14", FPU); + public static final Register f15 = new Register(47, 15, "f15", FPU); + + public static final Register f16 = new Register(48, 16, "f16", FPU); + public static final Register f17 = new Register(49, 17, "f17", FPU); + public static final Register f18 = new Register(50, 18, "f18", FPU); + public static final Register f19 = new Register(51, 19, "f19", FPU); + public static final Register f20 = new Register(52, 20, "f20", FPU); + public static final Register f21 = new Register(53, 21, "f21", FPU); + public static final Register f22 = new Register(54, 22, "f22", FPU); + public static final Register f23 = new Register(55, 23, "f23", FPU); + + public static final Register f24 = new Register(56, 24, "f24", FPU); + public static final Register f25 = new Register(57, 25, "f25", FPU); + public static final Register f26 = new Register(58, 26, "f26", FPU); + public static final Register f27 = new Register(59, 27, "f27", FPU); + public static final Register f28 = new Register(60, 28, "f28", FPU); + public static final Register f29 = new Register(61, 29, "f29", FPU); + public static final Register f30 = new Register(62, 30, "f30", FPU); + public static final Register f31 = new Register(63, 31, "f31", FPU); + + // @formatter:off + public static final Register[] fpuRegisters = { + f0, f1, f2, f3, f4, f5, f6, f7, + f8, f9, f10, f11, f12, f13, f14, f15, + f16, f17, f18, f19, f20, f21, f22, f23, + f24, f25, f26, f27, f28, f29, f30, f31 + }; + // @formatter:on + + // @formatter:off public static final Register[] allRegisters = { // CPU r0, r1, r2, r3, r4, r5, r6, r7, @@ -138,9 +178,16 @@ r24, r25, r26, r27, r28, r29, r30, r31, // FPU f0, f1, f2, f3, f4, f5, f6, f7, + f8, f9, f10, f11, f12, f13, f14, f15, + f16, f17, f18, f19, f20, f21, f22, f23, + f24, f25, f26, f27, f28, f29, f30, f31 }; + // @formatter:on - // @formatter:on + /** + * Stack bias for stack and frame pointer loads. + */ + public static final int STACK_BIAS = 0x7ff; public SPARC() { super("SPARC", 8, ByteOrder.BIG_ENDIAN, false, allRegisters, LOAD_STORE | STORE_STORE, 1, r31.encoding + 1, 8); diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.test/src/com/oracle/graal/test/GraalLongUnitTest.java --- a/graal/com.oracle.graal.test/src/com/oracle/graal/test/GraalLongUnitTest.java Fri Apr 25 16:21:07 2014 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,44 +0,0 @@ -/* - * 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.test; - -import java.util.*; - -import org.junit.*; -import org.junit.runners.*; -import org.junit.runners.model.*; - -public class GraalLongUnitTest extends BlockJUnit4ClassRunner { - - public GraalLongUnitTest(Class klass) throws InitializationError { - super(klass); - } - - @Override - protected List computeTestMethods() { - List methods = new ArrayList<>(5); - methods.addAll(getTestClass().getAnnotatedMethods(Test.class)); - methods.addAll(getTestClass().getAnnotatedMethods(LongTest.class)); - return methods; - } -} diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.test/src/com/oracle/graal/test/GraalTest.java --- a/graal/com.oracle.graal.test/src/com/oracle/graal/test/GraalTest.java Fri Apr 25 16:21:07 2014 +0200 +++ b/graal/com.oracle.graal.test/src/com/oracle/graal/test/GraalTest.java Mon Apr 28 11:18:15 2014 +0200 @@ -26,14 +26,12 @@ import java.util.*; import org.junit.*; -import org.junit.runner.*; /** * Base class for Graal tests. *

* This contains common utility methods that are used in multiple test projects. */ -@RunWith(GraalLongUnitTest.class) public class GraalTest { protected Method getMethod(String methodName) { diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.test/src/com/oracle/graal/test/LongTest.java --- a/graal/com.oracle.graal.test/src/com/oracle/graal/test/LongTest.java Fri Apr 25 16:21:07 2014 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,43 +0,0 @@ -/* - * 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.test; - -import java.lang.annotation.*; - -/* copy of org.junit.Test */ -@Retention(RetentionPolicy.RUNTIME) -@Target({ElementType.METHOD}) -public @interface LongTest { - - static final class None extends Throwable { - - private static final long serialVersionUID = 1L; - - private None() { - } - } - - Class expected() default None.class; - - long timeout() default 0L; -} diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.truffle.hotspot.amd64/src/com/oracle/graal/truffle/hotspot/amd64/AMD64OptimizedCallTargetInstrumentationFactory.java --- a/graal/com.oracle.graal.truffle.hotspot.amd64/src/com/oracle/graal/truffle/hotspot/amd64/AMD64OptimizedCallTargetInstrumentationFactory.java Fri Apr 25 16:21:07 2014 +0200 +++ b/graal/com.oracle.graal.truffle.hotspot.amd64/src/com/oracle/graal/truffle/hotspot/amd64/AMD64OptimizedCallTargetInstrumentationFactory.java Mon Apr 28 11:18:15 2014 +0200 @@ -31,7 +31,6 @@ import com.oracle.graal.asm.amd64.*; import com.oracle.graal.asm.amd64.AMD64Assembler.ConditionFlag; import com.oracle.graal.hotspot.*; -import com.oracle.graal.hotspot.amd64.*; import com.oracle.graal.hotspot.meta.*; import com.oracle.graal.lir.*; import com.oracle.graal.lir.asm.*; @@ -50,22 +49,9 @@ AMD64MacroAssembler asm = (AMD64MacroAssembler) this.asm; Register thisRegister = codeCache.getRegisterConfig().getCallingConventionRegisters(Type.JavaCall, Kind.Object)[0]; Register spillRegister = AMD64.r10; // TODO(mg): fix me - AMD64Address nMethodAddress = new AMD64Address(thisRegister, getFieldOffset("installedCode", OptimizedCallTarget.class)); - int verifiedEntryPoint = asm.position(); - if (config.useCompressedOops) { - asm.movl(spillRegister, nMethodAddress); - asm.nop(AMD64HotSpotBackend.PATCHED_VERIFIED_ENTRY_POINT_INSTRUCTION_SIZE - (asm.position() - verifiedEntryPoint)); - AMD64HotSpotMove.decodePointer(asm, spillRegister, registers.getHeapBaseRegister(), config.getOopEncoding()); - } else { - asm.movq(spillRegister, nMethodAddress); - asm.nop(AMD64HotSpotBackend.PATCHED_VERIFIED_ENTRY_POINT_INSTRUCTION_SIZE - (asm.position() - verifiedEntryPoint)); - } Label doProlog = new Label(); - asm.cmpq(spillRegister, 0); - asm.jcc(ConditionFlag.Equal, doProlog); - - AMD64Address codeBlobAddress = new AMD64Address(spillRegister, getFieldOffset("codeBlob", HotSpotInstalledCode.class)); + AMD64Address codeBlobAddress = new AMD64Address(thisRegister, getFieldOffset("address", InstalledCode.class)); asm.movq(spillRegister, codeBlobAddress); asm.cmpq(spillRegister, 0); asm.jcc(ConditionFlag.Equal, doProlog); diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.truffle.hotspot/src/com/oracle/graal/truffle/hotspot/HotSpotFrameInstance.java --- a/graal/com.oracle.graal.truffle.hotspot/src/com/oracle/graal/truffle/hotspot/HotSpotFrameInstance.java Fri Apr 25 16:21:07 2014 +0200 +++ b/graal/com.oracle.graal.truffle.hotspot/src/com/oracle/graal/truffle/hotspot/HotSpotFrameInstance.java Mon Apr 28 11:18:15 2014 +0200 @@ -25,16 +25,16 @@ import java.lang.reflect.*; import com.oracle.graal.api.code.stack.*; -import com.oracle.graal.graph.*; +import com.oracle.graal.compiler.common.*; +import com.oracle.graal.truffle.*; import com.oracle.truffle.api.*; import com.oracle.truffle.api.CompilerDirectives.SlowPath; import com.oracle.truffle.api.frame.*; -import com.oracle.truffle.api.impl.*; import com.oracle.truffle.api.nodes.*; public abstract class HotSpotFrameInstance implements FrameInstance { - private final InspectedFrame stackFrame; + protected final InspectedFrame stackFrame; public HotSpotFrameInstance(InspectedFrame stackFrame) { this.stackFrame = stackFrame; @@ -51,13 +51,15 @@ if (access == FrameAccess.NONE) { return null; } - if (!slowPath) { + if (!slowPath && getNotifyIndex() != -1) { MaterializedFrameNotify notify = (MaterializedFrameNotify) stackFrame.getLocal(getNotifyIndex()); - if (access.ordinal() > notify.getOutsideFrameAccess().ordinal()) { - notify.setOutsideFrameAccess(access); - } - if (stackFrame.isVirtual(getFrameIndex())) { - stackFrame.materializeVirtualObjects(true); + if (notify != null) { + if (access.ordinal() > notify.getOutsideFrameAccess().ordinal()) { + notify.setOutsideFrameAccess(access); + } + if (stackFrame.isVirtual(getFrameIndex())) { + stackFrame.materializeVirtualObjects(true); + } } } switch (access) { @@ -82,29 +84,28 @@ return stackFrame.isVirtual(getFrameIndex()); } - public CallTarget getCallTarget() { - return (CallTarget) stackFrame.getLocal(getCallTargetIndex()); - } + public abstract CallTarget getCallTarget(); - public CallNode getCallNode() { + public abstract CallTarget getTargetCallTarget(); + + public Node getCallNode() { Object receiver = stackFrame.getLocal(getNotifyIndex()); - if (receiver instanceof CallNode) { - return (CallNode) receiver; - } else { - return null; + if (receiver instanceof DirectCallNode || receiver instanceof IndirectCallNode) { + return (Node) receiver; } + return null; } /** * This class represents a frame that is taken from the - * {@link DefaultCallNode#callProxy(MaterializedFrameNotify, CallTarget, VirtualFrame, Object[])} + * {@link OptimizedDirectCallNode#callProxy(MaterializedFrameNotify, CallTarget, VirtualFrame, Object[], boolean, boolean)} * method. */ - public static final class NextFrame extends HotSpotFrameInstance { + public static final class CallNodeFrame extends HotSpotFrameInstance { public static final Method METHOD; static { try { - METHOD = DefaultCallNode.class.getDeclaredMethod("callProxy", MaterializedFrameNotify.class, CallTarget.class, VirtualFrame.class, Object[].class); + METHOD = OptimizedDirectCallNode.class.getDeclaredMethod("callProxy", MaterializedFrameNotify.class, CallTarget.class, VirtualFrame.class, Object[].class, boolean.class, boolean.class); } catch (NoSuchMethodException | SecurityException e) { throw new GraalInternalError(e); } @@ -113,7 +114,7 @@ private static final int CALL_TARGET_INDEX = 1; private static final int FRAME_INDEX = 2; - public NextFrame(InspectedFrame stackFrame) { + public CallNodeFrame(InspectedFrame stackFrame) { super(stackFrame); } @@ -131,6 +132,16 @@ protected int getFrameIndex() { return FRAME_INDEX; } + + @Override + public CallTarget getCallTarget() { + return getCallNode().getRootNode().getCallTarget(); + } + + @Override + public CallTarget getTargetCallTarget() { + return (CallTarget) stackFrame.getLocal(getCallTargetIndex()); + } } /** @@ -138,26 +149,28 @@ * {@link RootCallTarget#callProxy(VirtualFrame)} method. */ @SuppressWarnings("javadoc") - public static final class CurrentFrame extends HotSpotFrameInstance { + public static final class CallTargetFrame extends HotSpotFrameInstance { public static final Method METHOD; static { try { - METHOD = RootCallTarget.class.getDeclaredMethod("callProxy", VirtualFrame.class); + METHOD = OptimizedCallTarget.class.getDeclaredMethod("callProxy", VirtualFrame.class); } catch (NoSuchMethodException | SecurityException e) { throw new GraalInternalError(e); } } - private static final int NOTIFY_INDEX = 0; + private static final int NOTIFY_INDEX = -1; private static final int CALL_TARGET_INDEX = 0; private static final int FRAME_INDEX = 1; + private final boolean currentFrame; - public CurrentFrame(InspectedFrame stackFrame) { + public CallTargetFrame(InspectedFrame stackFrame, boolean currentFrame) { super(stackFrame); + this.currentFrame = currentFrame; } @Override public Frame getFrame(FrameAccess access, boolean slowPath) { - if (!slowPath) { + if (!slowPath && currentFrame) { throw new UnsupportedOperationException("cannot access current frame as fast path"); } return super.getFrame(access, slowPath); @@ -177,5 +190,15 @@ protected int getFrameIndex() { return FRAME_INDEX; } + + @Override + public CallTarget getCallTarget() { + return (CallTarget) stackFrame.getLocal(getCallTargetIndex()); + } + + @Override + public CallTarget getTargetCallTarget() { + return null; + } } } diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.truffle.hotspot/src/com/oracle/graal/truffle/hotspot/HotSpotOptimizedCallTarget.java --- a/graal/com.oracle.graal.truffle.hotspot/src/com/oracle/graal/truffle/hotspot/HotSpotOptimizedCallTarget.java Fri Apr 25 16:21:07 2014 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,189 +0,0 @@ -/* - * 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.truffle.hotspot; - -import static com.oracle.graal.truffle.TruffleCompilerOptions.*; - -import java.util.concurrent.*; - -import com.oracle.graal.api.code.*; -import com.oracle.graal.hotspot.meta.*; -import com.oracle.graal.truffle.*; -import com.oracle.truffle.api.*; -import com.oracle.truffle.api.nodes.*; - -/** - * Call target for running truffle on a standard VM (and not in SubstrateVM). - */ -public final class HotSpotOptimizedCallTarget extends OptimizedCallTarget { - - protected final TruffleCompiler compiler; - private Future installedCodeTask; - private SpeculationLog speculationLog = new HotSpotSpeculationLog(); - - HotSpotOptimizedCallTarget(RootNode rootNode, TruffleCompiler compiler, int invokeCounter, int compilationThreshold, boolean compilationEnabled) { - super(rootNode, invokeCounter, compilationThreshold, compilationEnabled, TruffleUseTimeForCompilationDecision.getValue() ? new TimedCompilationPolicy() : new DefaultCompilationPolicy()); - this.compiler = compiler; - } - - @Override - public SpeculationLog getSpeculationLog() { - return speculationLog; - } - - public boolean isOptimized() { - return installedCode != null || installedCodeTask != null; - } - - @CompilerDirectives.SlowPath - @Override - public Object call(Object[] args) { - return CompilerDirectives.inInterpreter() ? callHelper(args) : executeHelper(args); - } - - private Object callHelper(Object[] args) { - if (installedCode != null && installedCode.isValid()) { - reinstallCallMethodShortcut(); - } - if (TruffleCallTargetProfiling.getValue()) { - callCount++; - } - if (CompilerDirectives.injectBranchProbability(CompilerDirectives.FASTPATH_PROBABILITY, installedCode != null)) { - try { - return installedCode.executeVarargs(new Object[]{this, args}); - } catch (InvalidInstalledCodeException ex) { - return compiledCodeInvalidated(args); - } - } else { - return interpreterCall(args); - } - } - - private static void reinstallCallMethodShortcut() { - if (TraceTruffleCompilation.getValue()) { - OUT.println("[truffle] reinstall OptimizedCallTarget.call code with frame prolog shortcut."); - } - HotSpotTruffleRuntime.installOptimizedCallTargetCallMethod(); - } - - private Object compiledCodeInvalidated(Object[] args) { - invalidate(null, null, "Compiled code invalidated"); - return call(args); - } - - @Override - protected void invalidate(Node oldNode, Node newNode, CharSequence reason) { - InstalledCode m = this.installedCode; - if (m != null) { - CompilerAsserts.neverPartOfCompilation(); - installedCode = null; - inliningResult = null; - compilationProfile.reportInvalidated(); - logOptimizedInvalidated(this, oldNode, newNode, reason); - } - cancelInstalledTask(oldNode, newNode, reason); - } - - @Override - protected void cancelInstalledTask(Node oldNode, Node newNode, CharSequence reason) { - Future task = this.installedCodeTask; - if (task != null) { - task.cancel(true); - this.installedCodeTask = null; - logOptimizingUnqueued(this, oldNode, newNode, reason); - compilationProfile.reportInvalidated(); - } - } - - private Object interpreterCall(Object[] args) { - CompilerAsserts.neverPartOfCompilation(); - compilationProfile.reportInterpreterCall(); - - if (compilationEnabled && compilationPolicy.shouldCompile(compilationProfile)) { - InstalledCode code = compile(); - if (code != null && code.isValid()) { - this.installedCode = code; - try { - return code.executeVarargs(new Object[]{this, args}); - } catch (InvalidInstalledCodeException ex) { - return compiledCodeInvalidated(args); - } - } - } - return executeHelper(args); - } - - private boolean isCompiling() { - Future codeTask = this.installedCodeTask; - if (codeTask != null) { - if (codeTask.isCancelled()) { - installedCodeTask = null; - return false; - } - return true; - } - return false; - } - - @Override - public InstalledCode compile() { - if (isCompiling()) { - if (installedCodeTask.isDone()) { - return receiveInstalledCode(); - } - return null; - } else { - performInlining(); - cancelInlinedCallOptimization(); - logOptimizingQueued(this); - this.installedCodeTask = compiler.compile(this); - if (!TruffleBackgroundCompilation.getValue()) { - return receiveInstalledCode(); - } - return null; - } - } - - private InstalledCode receiveInstalledCode() { - try { - return installedCodeTask.get(); - } catch (InterruptedException | ExecutionException e) { - compilationEnabled = false; - logOptimizingFailed(this, e.getMessage()); - if (e.getCause() instanceof BailoutException) { - // Bailout => move on. - } else { - if (TraceTruffleCompilationExceptions.getValue()) { - e.printStackTrace(OUT); - } - if (TruffleCompilationExceptionsAreFatal.getValue()) { - System.exit(-1); - } - } - return null; - } finally { - onCompilationDone(); - } - } - -} diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.truffle.hotspot/src/com/oracle/graal/truffle/hotspot/HotSpotTruffleReplacements.java --- a/graal/com.oracle.graal.truffle.hotspot/src/com/oracle/graal/truffle/hotspot/HotSpotTruffleReplacements.java Fri Apr 25 16:21:07 2014 +0200 +++ b/graal/com.oracle.graal.truffle.hotspot/src/com/oracle/graal/truffle/hotspot/HotSpotTruffleReplacements.java Mon Apr 28 11:18:15 2014 +0200 @@ -28,7 +28,6 @@ import com.oracle.graal.phases.util.*; import com.oracle.graal.runtime.*; import com.oracle.graal.truffle.*; -import com.oracle.graal.truffle.hotspot.substitutions.*; public final class HotSpotTruffleReplacements extends TruffleReplacements { @@ -41,10 +40,4 @@ SnippetReflectionProvider snippetReflection = Graal.getRequiredCapability(SnippetReflectionProvider.class); return new HotSpotTruffleReplacements(providers, snippetReflection); } - - @Override - protected void registerTruffleSubstitutions() { - super.registerTruffleSubstitutions(); - registerSubstitutions(HotSpotOptimizedCallTargetSubstitutions.class); - } } diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.truffle.hotspot/src/com/oracle/graal/truffle/hotspot/HotSpotTruffleRuntime.java --- a/graal/com.oracle.graal.truffle.hotspot/src/com/oracle/graal/truffle/hotspot/HotSpotTruffleRuntime.java Fri Apr 25 16:21:07 2014 +0200 +++ b/graal/com.oracle.graal.truffle.hotspot/src/com/oracle/graal/truffle/hotspot/HotSpotTruffleRuntime.java Mon Apr 28 11:18:15 2014 +0200 @@ -26,18 +26,20 @@ import static com.oracle.graal.compiler.GraalCompiler.*; import static com.oracle.graal.truffle.TruffleCompilerOptions.*; -import java.lang.reflect.*; import java.util.*; +import java.util.concurrent.*; import com.oracle.graal.api.code.*; import com.oracle.graal.api.code.CallingConvention.Type; import com.oracle.graal.api.code.stack.*; import com.oracle.graal.api.meta.*; import com.oracle.graal.api.runtime.*; +import com.oracle.graal.compiler.*; import com.oracle.graal.compiler.target.*; import com.oracle.graal.debug.*; import com.oracle.graal.debug.Debug.Scope; -import com.oracle.graal.graph.*; +import com.oracle.graal.hotspot.*; +import com.oracle.graal.hotspot.meta.*; import com.oracle.graal.java.*; import com.oracle.graal.lir.asm.*; import com.oracle.graal.nodes.*; @@ -46,6 +48,7 @@ import com.oracle.graal.phases.common.*; import com.oracle.graal.phases.tiers.*; import com.oracle.graal.phases.util.*; +import com.oracle.graal.printer.*; import com.oracle.graal.runtime.*; import com.oracle.graal.truffle.*; import com.oracle.truffle.api.*; @@ -63,14 +66,38 @@ return new HotSpotTruffleRuntime(); } - private TruffleCompiler truffleCompiler; + private TruffleCompilerImpl truffleCompiler; private Replacements truffleReplacements; private StackIntrospection stackIntrospection; private ArrayList includes; private ArrayList excludes; + private Map> compilations = new IdentityHashMap<>(); + private final ThreadPoolExecutor compileQueue; + + private final ResolvedJavaMethod[] callNodeMethod; + private final ResolvedJavaMethod[] callTargetMethod; + private final ResolvedJavaMethod[] anyFrameMethod; private HotSpotTruffleRuntime() { installOptimizedCallTargetCallMethod(); + + callNodeMethod = new ResolvedJavaMethod[]{getGraalProviders().getMetaAccess().lookupJavaMethod(HotSpotFrameInstance.CallNodeFrame.METHOD)}; + callTargetMethod = new ResolvedJavaMethod[]{getGraalProviders().getMetaAccess().lookupJavaMethod(HotSpotFrameInstance.CallTargetFrame.METHOD)}; + anyFrameMethod = new ResolvedJavaMethod[]{callNodeMethod[0], callTargetMethod[0]}; + + // Create compilation queue. + CompilerThreadFactory factory = new CompilerThreadFactory("TruffleCompilerThread", new CompilerThreadFactory.DebugConfigAccess() { + public GraalDebugConfig getDebugConfig() { + if (Debug.isEnabled()) { + GraalDebugConfig debugConfig = DebugEnvironment.initialize(TTY.out().out()); + debugConfig.dumpHandlers().add(new TruffleTreeDumpHandler()); + return debugConfig; + } else { + return null; + } + } + }); + compileQueue = new ThreadPoolExecutor(1, 1, 0L, TimeUnit.MILLISECONDS, new LinkedBlockingQueue(), factory); } public String getName() { @@ -78,20 +105,27 @@ } public RootCallTarget createCallTarget(RootNode rootNode) { - if (truffleCompiler == null) { - truffleCompiler = new TruffleCompilerImpl(); + CompilationPolicy compilationPolicy; + if (acceptForCompilation(rootNode)) { + compilationPolicy = new CounterBasedCompilationPolicy(); + } else { + compilationPolicy = new InterpreterOnlyCompilationPolicy(); } - return new HotSpotOptimizedCallTarget(rootNode, truffleCompiler, TruffleMinInvokeThreshold.getValue(), TruffleCompilationThreshold.getValue(), acceptForCompilation(rootNode)); + return new OptimizedCallTarget(rootNode, this, TruffleMinInvokeThreshold.getValue(), TruffleCompilationThreshold.getValue(), compilationPolicy, new HotSpotSpeculationLog()); } - public CallNode createCallNode(CallTarget target) { + public DirectCallNode createDirectCallNode(CallTarget target) { if (target instanceof OptimizedCallTarget) { - return OptimizedCallNode.create((OptimizedCallTarget) target); + return OptimizedDirectCallNode.create((OptimizedCallTarget) target); } else { - return new DefaultCallNode(target); + return new DefaultDirectCallNode(target); } } + public IndirectCallNode createIndirectCallNode() { + return new OptimizedIndirectCallNode(); + } + @Override public VirtualFrame createVirtualFrame(Object[] arguments, FrameDescriptor frameDescriptor) { return OptimizedCallTarget.createFrame(frameDescriptor, arguments); @@ -166,24 +200,18 @@ public static void installOptimizedCallTargetCallMethod() { Providers providers = getGraalProviders(); MetaAccessProvider metaAccess = providers.getMetaAccess(); - CodeCacheProvider codeCache = providers.getCodeCache(); - ResolvedJavaMethod resolvedCallMethod = metaAccess.lookupJavaMethod(getCallMethod()); - CompilationResult compResult = compileMethod(resolvedCallMethod); - try (Scope s = Debug.scope("CodeInstall", codeCache, resolvedCallMethod)) { - codeCache.setDefaultMethod(resolvedCallMethod, compResult); + ResolvedJavaType type = metaAccess.lookupJavaType(OptimizedCallTarget.class); + for (ResolvedJavaMethod method : type.getDeclaredMethods()) { + if (method.getAnnotation(TruffleCallBoundary.class) != null) { + CompilationResult compResult = compileMethod(method); + CodeCacheProvider codeCache = providers.getCodeCache(); + try (Scope s = Debug.scope("CodeInstall", codeCache, method)) { + codeCache.setDefaultMethod(method, compResult); + } + } } } - private static Method getCallMethod() { - Method method; - try { - method = HotSpotOptimizedCallTarget.class.getDeclaredMethod("call", new Class[]{Object[].class}); - } catch (NoSuchMethodException | SecurityException e) { - throw GraalInternalError.shouldNotReachHere(); - } - return method; - } - private static CompilationResultBuilderFactory getOptimizedCallTargetInstrumentationFactory(String arch, ResolvedJavaMethod method) { for (OptimizedCallTargetInstrumentationFactory factory : ServiceLoader.loadInstalled(OptimizedCallTargetInstrumentationFactory.class)) { if (factory.getArchitecture().equals(arch)) { @@ -221,16 +249,24 @@ if (stackIntrospection == null) { stackIntrospection = Graal.getRequiredCapability(StackIntrospection.class); } - ResolvedJavaMethod method = getGraalProviders().getMetaAccess().lookupJavaMethod(HotSpotFrameInstance.NextFrame.METHOD); - final Iterator frames = stackIntrospection.getStackTrace(method, method).iterator(); + final Iterator frames = stackIntrospection.getStackTrace(anyFrameMethod, anyFrameMethod, 1).iterator(); class FrameIterator implements Iterator { + public boolean hasNext() { return frames.hasNext(); } public FrameInstance next() { InspectedFrame frame = frames.next(); - return new HotSpotFrameInstance.NextFrame(frame); + if (frame.getMethod().equals(callNodeMethod[0])) { + assert frames.hasNext(); + InspectedFrame calltarget2 = frames.next(); + assert calltarget2.getMethod().equals(callTargetMethod[0]); + return new HotSpotFrameInstance.CallNodeFrame(frame); + } else { + assert frame.getMethod().equals(callTargetMethod[0]); + return new HotSpotFrameInstance.CallTargetFrame(frame, false); + } } } return new Iterable() { @@ -244,13 +280,64 @@ if (stackIntrospection == null) { stackIntrospection = Graal.getRequiredCapability(StackIntrospection.class); } - ResolvedJavaMethod method = getGraalProviders().getMetaAccess().lookupJavaMethod(HotSpotFrameInstance.CurrentFrame.METHOD); - Iterator frames = stackIntrospection.getStackTrace(method, method).iterator(); + Iterator frames = stackIntrospection.getStackTrace(callTargetMethod, callTargetMethod, 0).iterator(); if (frames.hasNext()) { - return new HotSpotFrameInstance.CurrentFrame(frames.next()); + return new HotSpotFrameInstance.CallTargetFrame(frames.next(), true); } else { System.out.println("no current frame found"); return null; } } + + public void compile(OptimizedCallTarget optimizedCallTarget, boolean mayBeAsynchronous) { + if (truffleCompiler == null) { + truffleCompiler = new TruffleCompilerImpl(); + } + Runnable r = new Runnable() { + @Override + public void run() { + try (Scope s = Debug.scope("Truffle", new TruffleDebugJavaMethod(optimizedCallTarget))) { + truffleCompiler.compileMethodImpl(optimizedCallTarget); + optimizedCallTarget.compilationFinished(null); + } catch (Throwable e) { + optimizedCallTarget.compilationFinished(e); + } + } + }; + if (mayBeAsynchronous) { + Future future = compileQueue.submit(r); + this.compilations.put(optimizedCallTarget, future); + } else { + r.run(); + } + } + + public boolean cancelInstalledTask(OptimizedCallTarget optimizedCallTarget) { + Future codeTask = this.compilations.get(optimizedCallTarget); + if (codeTask != null && isCompiling(optimizedCallTarget)) { + this.compilations.remove(optimizedCallTarget); + return codeTask.cancel(true); + } + return false; + } + + public boolean isCompiling(OptimizedCallTarget optimizedCallTarget) { + Future codeTask = this.compilations.get(optimizedCallTarget); + if (codeTask != null) { + if (codeTask.isCancelled() || codeTask.isDone()) { + this.compilations.remove(optimizedCallTarget); + return false; + } + return true; + } + return false; + } + + public void invalidateInstalledCode(OptimizedCallTarget optimizedCallTarget) { + HotSpotGraalRuntime.runtime().getCompilerToVM().invalidateInstalledCode(optimizedCallTarget); + } + + public void reinstallStubs() { + installOptimizedCallTargetCallMethod(); + } } diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.truffle.hotspot/src/com/oracle/graal/truffle/hotspot/OptimizedCallTargetInstrumentation.java --- a/graal/com.oracle.graal.truffle.hotspot/src/com/oracle/graal/truffle/hotspot/OptimizedCallTargetInstrumentation.java Fri Apr 25 16:21:07 2014 +0200 +++ b/graal/com.oracle.graal.truffle.hotspot/src/com/oracle/graal/truffle/hotspot/OptimizedCallTargetInstrumentation.java Mon Apr 28 11:18:15 2014 +0200 @@ -27,7 +27,7 @@ import com.oracle.graal.api.code.*; import com.oracle.graal.api.code.CompilationResult.Mark; import com.oracle.graal.asm.*; -import com.oracle.graal.graph.*; +import com.oracle.graal.compiler.common.*; import com.oracle.graal.hotspot.*; import com.oracle.graal.hotspot.meta.HotSpotCodeCacheProvider.MarkId; import com.oracle.graal.hotspot.meta.*; diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.truffle.hotspot/src/com/oracle/graal/truffle/hotspot/ReadOnlyFrame.java --- a/graal/com.oracle.graal.truffle.hotspot/src/com/oracle/graal/truffle/hotspot/ReadOnlyFrame.java Fri Apr 25 16:21:07 2014 +0200 +++ b/graal/com.oracle.graal.truffle.hotspot/src/com/oracle/graal/truffle/hotspot/ReadOnlyFrame.java Mon Apr 28 11:18:15 2014 +0200 @@ -22,7 +22,7 @@ */ package com.oracle.graal.truffle.hotspot; -import com.oracle.graal.graph.*; +import com.oracle.graal.compiler.common.*; import com.oracle.truffle.api.frame.*; class ReadOnlyFrame implements Frame { diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.truffle.hotspot/src/com/oracle/graal/truffle/hotspot/substitutions/HotSpotOptimizedCallTargetSubstitutions.java --- a/graal/com.oracle.graal.truffle.hotspot/src/com/oracle/graal/truffle/hotspot/substitutions/HotSpotOptimizedCallTargetSubstitutions.java Fri Apr 25 16:21:07 2014 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,42 +0,0 @@ -/* - * 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.truffle.hotspot.substitutions; - -import com.oracle.graal.api.replacements.*; -import com.oracle.graal.nodes.spi.*; -import com.oracle.graal.truffle.*; -import com.oracle.graal.truffle.hotspot.*; -import com.oracle.graal.truffle.nodes.asserts.*; - -@ClassSubstitution(HotSpotOptimizedCallTarget.class) -public class HotSpotOptimizedCallTargetSubstitutions { - - @MacroSubstitution(macro = NeverInlineMacroNode.class, isStatic = false) - public static native Object callHelper(OptimizedCallTarget target, Object[] args); - - @MacroSubstitution(macro = NeverInlineMacroNode.class, isStatic = false) - public static native Object interpreterCall(OptimizedCallTarget target, Object[] args); - - @MacroSubstitution(macro = NeverInlineMacroNode.class, isStatic = false) - public static native Object compiledCodeInvalidated(OptimizedCallTarget target, Object[] args); -} diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.truffle.test/src/com/oracle/graal/truffle/test/PartialEvaluationTest.java --- a/graal/com.oracle.graal.truffle.test/src/com/oracle/graal/truffle/test/PartialEvaluationTest.java Fri Apr 25 16:21:07 2014 +0200 +++ b/graal/com.oracle.graal.truffle.test/src/com/oracle/graal/truffle/test/PartialEvaluationTest.java Mon Apr 28 11:18:15 2014 +0200 @@ -64,7 +64,8 @@ protected InstalledCode assertPartialEvalEquals(String methodName, RootNode root, Object[] arguments) { Assumptions assumptions = new Assumptions(true); StructuredGraph actual = partialEval(root, arguments, assumptions, true); - InstalledCode result = truffleCompiler.compileMethodHelper(actual, assumptions, root.toString(), getSpeculationLog()); + InstalledCode result = new InstalledCode(); + truffleCompiler.compileMethodHelper(actual, assumptions, root.toString(), getSpeculationLog(), result); StructuredGraph expected = parseForComparison(methodName); removeFrameStates(actual); Assert.assertEquals(getCanonicalGraphString(expected, true, true), getCanonicalGraphString(actual, true, true)); diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/CompilationPolicy.java --- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/CompilationPolicy.java Fri Apr 25 16:21:07 2014 +0200 +++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/CompilationPolicy.java Mon Apr 28 11:18:15 2014 +0200 @@ -26,4 +26,6 @@ boolean shouldCompile(CompilationProfile profile); + void recordCompilationFailure(Throwable t); + } diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/CompilationProfile.java --- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/CompilationProfile.java Fri Apr 25 16:21:07 2014 +0200 +++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/CompilationProfile.java Mon Apr 28 11:18:15 2014 +0200 @@ -40,8 +40,6 @@ private long previousTimestamp; - private final String name; - private int callCount; private int callAndLoopCount; private int compilationCallThreshold; @@ -50,13 +48,17 @@ private final int originalInvokeCounter; private final int originalCompilationThreshold; - public CompilationProfile(final int compilationThreshold, final int initialInvokeCounter, final String name) { + public CompilationProfile(final int compilationThreshold, final int initialInvokeCounter) { this.previousTimestamp = System.nanoTime(); this.compilationCallThreshold = initialInvokeCounter; this.compilationCallAndLoopThreshold = compilationThreshold; this.originalInvokeCounter = initialInvokeCounter; this.originalCompilationThreshold = compilationThreshold; - this.name = name; + } + + @Override + public String toString() { + return String.format("CompilationProfile(callCount=%d/%d, callAndLoopCount=%d/%d)", callCount, compilationCallThreshold, callAndLoopCount, compilationCallAndLoopThreshold); } public Map getDebugProperties() { @@ -81,10 +83,6 @@ return previousTimestamp; } - public String getName() { - return this.name; - } - public int getInvalidationCount() { return invalidationCount; } diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/CounterBasedCompilationPolicy.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/CounterBasedCompilationPolicy.java Mon Apr 28 11:18:15 2014 +0200 @@ -0,0 +1,37 @@ +/* + * 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.truffle; + +public class CounterBasedCompilationPolicy implements CompilationPolicy { + + private boolean compilationFailed; + + public boolean shouldCompile(CompilationProfile profile) { + return !compilationFailed && profile.getCallCount() >= profile.getCompilationCallThreshold() && profile.getCallAndLoopCount() >= profile.getCompilationCallAndLoopThreshold(); + } + + public void recordCompilationFailure(Throwable t) { + compilationFailed = true; + } + +} diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/DefaultCompilationPolicy.java --- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/DefaultCompilationPolicy.java Fri Apr 25 16:21:07 2014 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,31 +0,0 @@ -/* - * 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.truffle; - -public class DefaultCompilationPolicy implements CompilationPolicy { - - public boolean shouldCompile(CompilationProfile profile) { - return profile.getCallCount() >= profile.getCompilationCallThreshold() && profile.getCallAndLoopCount() >= profile.getCompilationCallAndLoopThreshold(); - } - -} diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/DefaultInliningPolicy.java --- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/DefaultInliningPolicy.java Fri Apr 25 16:21:07 2014 +0200 +++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/DefaultInliningPolicy.java Mon Apr 28 11:18:15 2014 +0200 @@ -27,29 +27,25 @@ public class DefaultInliningPolicy implements TruffleInliningPolicy { private static final String REASON_RECURSION = "recursion"; - private static final String REASON_MAXIMUM_NODE_COUNT = "nodeCount * callSites > " + TruffleInliningMaxCallerSize.getValue(); + private static final String REASON_MAXIMUM_NODE_COUNT = "deepNodeCount * callSites > " + TruffleInliningMaxCallerSize.getValue(); private static final String REASON_MAXIMUM_TOTAL_NODE_COUNT = "totalNodeCount > " + TruffleInliningMaxCallerSize.getValue(); public double calculateScore(TruffleInliningProfile profile) { return profile.getFrequency() / profile.getDeepNodeCount(); } - public boolean isAllowed(TruffleInliningResult state, TruffleInliningProfile profile, int nodeCountBudget) { - TruffleCallPath callPath = profile.getCallPath(); - OptimizedCallTarget inlineTarget = callPath.getCallTarget(); - for (TruffleCallPath path : callPath.getParent().toList()) { - if (path.getCallTarget() == inlineTarget) { - // recursive call found - profile.setFailedReason(REASON_RECURSION); - return false; - } + public boolean isAllowed(TruffleInliningProfile profile, int currentBudgetLeft) { + if (profile.isRecursiveCall()) { + // recursive call found + profile.setFailedReason(REASON_RECURSION); + return false; } if (profile.isForced()) { return true; } - if (nodeCountBudget - profile.getDeepNodeCount() < 0) { + if (currentBudgetLeft - profile.getDeepNodeCount() < 0) { profile.setFailedReason(REASON_MAXIMUM_TOTAL_NODE_COUNT); return false; } @@ -62,9 +58,4 @@ return true; } - - public boolean isAllowedDeep(TruffleInliningResult state, TruffleInliningProfile profile, int nodeCountBudget) { - return true; - } - } diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/FrameWithoutBoxing.java --- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/FrameWithoutBoxing.java Fri Apr 25 16:21:07 2014 +0200 +++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/FrameWithoutBoxing.java Mon Apr 28 11:18:15 2014 +0200 @@ -45,10 +45,11 @@ public FrameWithoutBoxing(FrameDescriptor descriptor, Object[] arguments) { this.descriptor = descriptor; this.arguments = arguments; - this.locals = new Object[descriptor.getSize()]; + int size = descriptor.getSize(); + this.locals = new Object[size]; Arrays.fill(locals, descriptor.getTypeConversion().getDefaultValue()); - this.primitiveLocals = new long[descriptor.getSize()]; - this.tags = new byte[descriptor.getSize()]; + this.primitiveLocals = new long[size]; + this.tags = new byte[size]; } @Override diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/GraalTruffleRuntime.java --- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/GraalTruffleRuntime.java Fri Apr 25 16:21:07 2014 +0200 +++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/GraalTruffleRuntime.java Mon Apr 28 11:18:15 2014 +0200 @@ -28,4 +28,14 @@ public interface GraalTruffleRuntime extends TruffleRuntime { Replacements getReplacements(); + + void compile(OptimizedCallTarget optimizedCallTarget, boolean mayBeAsynchronous); + + boolean cancelInstalledTask(OptimizedCallTarget optimizedCallTarget); + + boolean isCompiling(OptimizedCallTarget optimizedCallTarget); + + void invalidateInstalledCode(OptimizedCallTarget optimizedCallTarget); + + void reinstallStubs(); } diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/InterpreterOnlyCompilationPolicy.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/InterpreterOnlyCompilationPolicy.java Mon Apr 28 11:18:15 2014 +0200 @@ -0,0 +1,34 @@ +/* + * 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.truffle; + +public class InterpreterOnlyCompilationPolicy implements CompilationPolicy { + + public boolean shouldCompile(CompilationProfile profile) { + return false; + } + + public void recordCompilationFailure(Throwable t) { + } + +} diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/MaterializedFrameNotify.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/MaterializedFrameNotify.java Mon Apr 28 11:18:15 2014 +0200 @@ -0,0 +1,32 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.graal.truffle; + +import com.oracle.truffle.api.frame.FrameInstance.*; + +public interface MaterializedFrameNotify { + + FrameAccess getOutsideFrameAccess(); + + void setOutsideFrameAccess(FrameAccess outsideFrameAccess); +} diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/OptimizedAssumption.java --- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/OptimizedAssumption.java Fri Apr 25 16:21:07 2014 +0200 +++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/OptimizedAssumption.java Mon Apr 28 11:18:15 2014 +0200 @@ -23,7 +23,6 @@ package com.oracle.graal.truffle; import java.lang.ref.*; -import java.util.*; import com.oracle.graal.api.code.*; import com.oracle.truffle.api.impl.*; @@ -31,7 +30,13 @@ public final class OptimizedAssumption extends AbstractAssumption { - List> dependentInstalledCode; + private static class Entry { + WeakReference installedCode; + long version; + Entry next; + } + + private Entry first; public OptimizedAssumption(String name) { super(name); @@ -47,25 +52,26 @@ @Override public synchronized void invalidate() { if (isValid) { - if (dependentInstalledCode != null) { - for (WeakReference installedCodeReference : dependentInstalledCode) { - InstalledCode installedCode = installedCodeReference.get(); - if (installedCode != null) { - installedCode.invalidate(); - } + Entry e = first; + while (e != null) { + InstalledCode installedCode = e.installedCode.get(); + if (installedCode != null && installedCode.getVersion() == e.version) { + installedCode.invalidate(); } - dependentInstalledCode = null; + e = e.next; } + first = null; isValid = false; } } public synchronized void registerInstalledCode(InstalledCode installedCode) { if (isValid) { - if (dependentInstalledCode == null) { - dependentInstalledCode = new ArrayList<>(); - } - dependentInstalledCode.add(new WeakReference<>(installedCode)); + Entry e = new Entry(); + e.installedCode = new WeakReference<>(installedCode); + e.version = installedCode.getVersion(); + e.next = first; + first = e; } else { installedCode.invalidate(); } diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/OptimizedCallNode.java --- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/OptimizedCallNode.java Fri Apr 25 16:21:07 2014 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,191 +0,0 @@ -/* - * 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.truffle; - -import java.util.concurrent.atomic.*; - -import com.oracle.truffle.api.*; -import com.oracle.truffle.api.CompilerDirectives.CompilationFinal; -import com.oracle.truffle.api.frame.*; -import com.oracle.truffle.api.impl.*; -import com.oracle.truffle.api.nodes.*; -import com.oracle.truffle.api.nodes.NodeUtil.NodeCountFilter; - -/** - * Call target that is optimized by Graal upon surpassing a specific invocation threshold. - */ -public final class OptimizedCallNode extends DefaultCallNode { - - protected int callCount; - private boolean trySplit = true; - private boolean inliningForced; - @CompilationFinal private OptimizedCallTarget splitCallTarget; - private final AtomicInteger inliningCounter = new AtomicInteger(0); - - private OptimizedCallNode(OptimizedCallTarget target) { - super(target); - } - - @Override - public boolean isSplittable() { - return getCallTarget().getRootNode().isSplittable(); - } - - @Override - public OptimizedCallTarget getCallTarget() { - return (OptimizedCallTarget) super.getCallTarget(); - } - - public int getCallCount() { - return callCount; - } - - @Override - public OptimizedCallTarget getCurrentCallTarget() { - return (OptimizedCallTarget) super.getCurrentCallTarget(); - } - - @Override - public OptimizedCallTarget getSplitCallTarget() { - return splitCallTarget; - } - - public static OptimizedCallNode create(OptimizedCallTarget target) { - return new OptimizedCallNode(target); - } - - @Override - public Object call(VirtualFrame frame, Object[] arguments) { - if (CompilerDirectives.inInterpreter()) { - interpreterCall(); - if (inliningCounter.get() > 0 || inliningForced) { - return getCurrentCallTarget().callInlined(arguments); - } - } - return callProxy(this, getCurrentCallTarget(), frame, arguments); - } - - private void interpreterCall() { - callCount++; - if (trySplit) { - if (callCount == 1) { - // on first call - getCurrentCallTarget().incrementKnownCallSite(); - } - if (callCount > 1) { - trySplit = false; - if (shouldSplit()) { - splitImpl(true); - } - } - } - } - - void notifyInlining() { - inliningCounter.incrementAndGet(); - } - - void notifyInliningDone() { - inliningCounter.decrementAndGet(); - } - - @Override - public void inline() { - inliningForced = true; - } - - @Override - public boolean isInlined() { - return inliningForced; - } - - private void splitImpl(boolean heuristic) { - CompilerAsserts.neverPartOfCompilation(); - - OptimizedCallTarget splitTarget = (OptimizedCallTarget) Truffle.getRuntime().createCallTarget(getCallTarget().getRootNode().split()); - splitTarget.setSplitSource(getCallTarget()); - if (heuristic) { - OptimizedCallTarget.logSplit(this, getCallTarget(), splitTarget); - } - if (callCount >= 1) { - getCallTarget().decrementKnownCallSite(); - splitTarget.incrementKnownCallSite(); - } - this.splitCallTarget = splitTarget; - } - - private boolean shouldSplit() { - if (splitCallTarget != null) { - return false; - } - if (!TruffleCompilerOptions.TruffleSplittingEnabled.getValue()) { - return false; - } - if (!isSplittable()) { - return false; - } - OptimizedCallTarget splitTarget = getCallTarget(); - int nodeCount = OptimizedCallUtils.countNonTrivialNodes(null, new TruffleCallPath(splitTarget)); - if (nodeCount > TruffleCompilerOptions.TruffleSplittingMaxCalleeSize.getValue()) { - return false; - } - - // disable recursive splitting for now - OptimizedCallTarget root = (OptimizedCallTarget) getRootNode().getCallTarget(); - if (root == splitTarget || root.getSplitSource() == splitTarget) { - // recursive call found - return false; - } - - // max one child call and callCount > 2 and kind of small number of nodes - if (isMaxSingleCall()) { - return true; - } - return countPolymorphic() >= 1; - } - - private boolean isMaxSingleCall() { - return NodeUtil.countNodes(getCurrentCallTarget().getRootNode(), new NodeCountFilter() { - public boolean isCounted(Node node) { - return node instanceof CallNode; - } - }) <= 1; - } - - private int countPolymorphic() { - return NodeUtil.countNodes(getCallTarget().getRootNode(), new NodeCountFilter() { - public boolean isCounted(Node node) { - NodeCost cost = node.getCost(); - boolean polymorphic = cost == NodeCost.POLYMORPHIC || cost == NodeCost.MEGAMORPHIC; - return polymorphic; - } - }); - } - - @SuppressWarnings("unused") - public void nodeReplaced(Node oldNode, Node newNode, CharSequence reason) { - if (!isSplit() && isSplittable()) { - trySplit = true; - } - } -} diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/OptimizedCallTarget.java --- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/OptimizedCallTarget.java Fri Apr 25 16:21:07 2014 +0200 +++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/OptimizedCallTarget.java Mon Apr 28 11:18:15 2014 +0200 @@ -22,6 +22,7 @@ */ package com.oracle.graal.truffle; +import static com.oracle.graal.truffle.OptimizedCallTargetLog.*; import static com.oracle.graal.truffle.TruffleCompilerOptions.*; import java.io.*; @@ -30,55 +31,177 @@ import com.oracle.graal.api.code.*; import com.oracle.graal.debug.*; -import com.oracle.graal.truffle.OptimizedCallUtils.InlinedNodeCountFilter; import com.oracle.truffle.api.*; +import com.oracle.truffle.api.CompilerDirectives.CompilationFinal; import com.oracle.truffle.api.frame.*; -import com.oracle.truffle.api.impl.*; import com.oracle.truffle.api.nodes.*; /** * Call target that is optimized by Graal upon surpassing a specific invocation threshold. */ -public abstract class OptimizedCallTarget extends DefaultCallTarget implements LoopCountReceiver, ReplaceObserver { +public class OptimizedCallTarget extends InstalledCode implements RootCallTarget, LoopCountReceiver, ReplaceObserver { protected static final PrintStream OUT = TTY.out().out(); - protected InstalledCode installedCode; - protected boolean compilationEnabled; + protected final GraalTruffleRuntime runtime; + private SpeculationLog speculationLog; protected int callCount; - protected TruffleInliningResult inliningResult; + protected boolean inliningPerformed; protected final CompilationProfile compilationProfile; protected final CompilationPolicy compilationPolicy; private OptimizedCallTarget splitSource; + private final AtomicInteger callSitesKnown = new AtomicInteger(0); + @CompilationFinal private Class[] profiledArgumentTypes; + @CompilationFinal private Assumption profiledArgumentTypesAssumption; + @CompilationFinal private Class profiledReturnType; + @CompilationFinal private Assumption profiledReturnTypeAssumption; - private final AtomicInteger callSitesKnown = new AtomicInteger(0); + private final RootNode rootNode; - public OptimizedCallTarget(RootNode rootNode, int invokeCounter, int compilationThreshold, boolean compilationEnabled, CompilationPolicy compilationPolicy) { - super(rootNode); - this.compilationEnabled = compilationEnabled; + public final RootNode getRootNode() { + return rootNode; + } + + public OptimizedCallTarget(RootNode rootNode, GraalTruffleRuntime runtime, int invokeCounter, int compilationThreshold, CompilationPolicy compilationPolicy, SpeculationLog speculationLog) { + this.runtime = runtime; + this.speculationLog = speculationLog; + this.rootNode = rootNode; + this.rootNode.adoptChildren(); + this.rootNode.setCallTarget(this); this.compilationPolicy = compilationPolicy; - this.compilationProfile = new CompilationProfile(compilationThreshold, invokeCounter, rootNode.toString()); + this.compilationProfile = new CompilationProfile(compilationThreshold, invokeCounter); if (TruffleCallTargetProfiling.getValue()) { registerCallTarget(this); } } + public SpeculationLog getSpeculationLog() { + return speculationLog; + } + + @Override + public Object call(Object... args) { + return callBoundary(args); + } + + public Object callDirect(Object... args) { + if (profiledArgumentTypesAssumption == null) { + CompilerDirectives.transferToInterpreter(); + profiledArgumentTypesAssumption = Truffle.getRuntime().createAssumption("Profiled Argument Types"); + profiledArgumentTypes = new Class[args.length]; + } else if (profiledArgumentTypes != null) { + if (profiledArgumentTypes.length != args.length) { + CompilerDirectives.transferToInterpreter(); + profiledArgumentTypesAssumption.invalidate(); + profiledArgumentTypes = null; + } + } + + Object result = callBoundary(args); + Class klass = profiledReturnType; + if (klass != null && CompilerDirectives.inCompiledCode() && profiledReturnTypeAssumption.isValid()) { + result = CompilerDirectives.unsafeCast(result, klass, true, true); + } + return result; + } + + @TruffleCallBoundary + private Object callBoundary(Object[] args) { + if (CompilerDirectives.inInterpreter()) { + // We are called and we are still in Truffle interpreter mode. + CompilerDirectives.transferToInterpreter(); + interpreterCall(); + } else { + // We come here from compiled code (i.e., we have been inlined). + } + + return callRoot(args); + } + + @Override + public void invalidate() { + this.runtime.invalidateInstalledCode(this); + } + + protected void invalidate(Node oldNode, Node newNode, CharSequence reason) { + if (isValid()) { + CompilerAsserts.neverPartOfCompilation(); + invalidate(); + compilationProfile.reportInvalidated(); + logOptimizedInvalidated(this, oldNode, newNode, reason); + } + cancelInstalledTask(oldNode, newNode, reason); + } + + private void cancelInstalledTask(Node oldNode, Node newNode, CharSequence reason) { + if (this.runtime.cancelInstalledTask(this)) { + logOptimizingUnqueued(this, oldNode, newNode, reason); + compilationProfile.reportInvalidated(); + } + } + + private void interpreterCall() { + CompilerAsserts.neverPartOfCompilation(); + if (this.isValid()) { + // Stubs were deoptimized => reinstall. + this.runtime.reinstallStubs(); + } else { + compilationProfile.reportInterpreterCall(); + if (TruffleCallTargetProfiling.getValue()) { + callCount++; + } + if (compilationPolicy.shouldCompile(compilationProfile)) { + compile(); + } + } + } + + public void compile() { + if (!runtime.isCompiling(this)) { + performInlining(); + logOptimizingQueued(this); + runtime.compile(this, TruffleBackgroundCompilation.getValue()); + } + } + + public void compilationFinished(Throwable t) { + if (t == null) { + // Compilation was successful. + } else { + compilationPolicy.recordCompilationFailure(t); + logOptimizingFailed(this, t.getMessage()); + if (t instanceof BailoutException) { + // Bailout => move on. + } else { + if (TruffleCompilationExceptionsAreFatal.getValue()) { + t.printStackTrace(OUT); + System.exit(-1); + } + } + } + } + + protected final Object callProxy(VirtualFrame frame) { + try { + return getRootNode().execute(frame); + } finally { + // this assertion is needed to keep the values from being cleared as non-live locals + assert frame != null && this != null; + } + } + public final int getKnownCallSiteCount() { return callSitesKnown.get(); } - public final void incrementKnownCallSite() { + public final void incrementKnownCallSites() { callSitesKnown.incrementAndGet(); } - public final void decrementKnownCallSite() { + public final void decrementKnownCallSites() { callSitesKnown.decrementAndGet(); } - public final TruffleInliningResult getInliningResult() { - return inliningResult; - } - public final OptimizedCallTarget getSplitSource() { return splitSource; } @@ -89,8 +212,8 @@ @Override public String toString() { - String superString = super.toString(); - if (installedCode != null) { + String superString = rootNode.toString(); + if (isValid()) { superString += " "; } if (splitSource != null) { @@ -103,76 +226,77 @@ return compilationProfile; } - @Override - public abstract Object call(Object[] args); - - public abstract InstalledCode compile(); - public final Object callInlined(Object[] arguments) { if (CompilerDirectives.inInterpreter()) { compilationProfile.reportInlinedCall(); } - return executeHelper(arguments); + VirtualFrame frame = createFrame(getRootNode().getFrameDescriptor(), arguments); + return callProxy(frame); } public final void performInlining() { - if (!shouldInline()) { + if (!TruffleFunctionInlining.getValue()) { return; } - - if (inliningResult != null) { + if (inliningPerformed) { return; } - - TruffleInliningHandler handler = new TruffleInliningHandler(this, new DefaultInliningPolicy(), new HashMap()); - int startNodeCount = OptimizedCallUtils.countNonTrivialNodes(null, new TruffleCallPath(this)); - this.inliningResult = handler.inline(startNodeCount); - logInliningDecision(this, inliningResult, handler); + TruffleInliningHandler handler = new TruffleInliningHandler(new DefaultInliningPolicy()); + TruffleInliningResult result = handler.decideInlining(this, 0); + performInlining(result); + logInliningDecision(result); } - protected boolean shouldCompile() { - return compilationPolicy.shouldCompile(compilationProfile); - } - - protected static boolean shouldInline() { - return TruffleFunctionInlining.getValue(); - } - - protected final void cancelInlinedCallOptimization() { - if (getInliningResult() != null) { - for (TruffleCallPath path : getInliningResult()) { - OptimizedCallNode top = path.getCallNode(); - top.notifyInlining(); - top.getCurrentCallTarget().cancelInstalledTask(top, top, "Inlined"); + private static void performInlining(TruffleInliningResult result) { + if (result.getCallTarget().inliningPerformed) { + return; + } + result.getCallTarget().inliningPerformed = true; + for (TruffleInliningProfile profile : result) { + profile.getCallNode().inline(); + TruffleInliningResult recursiveResult = profile.getRecursiveResult(); + if (recursiveResult != null) { + performInlining(recursiveResult); } } } - protected final void onCompilationDone() { - if (inliningResult != null) { - for (TruffleCallPath path : inliningResult) { - path.getCallNode().notifyInliningDone(); + public final Object callRoot(Object[] originalArguments) { + + Object[] args = originalArguments; + if (this.profiledArgumentTypesAssumption != null && CompilerDirectives.inCompiledCode() && profiledArgumentTypesAssumption.isValid()) { + args = CompilerDirectives.unsafeCast(castArrayFixedLength(args, profiledArgumentTypes.length), Object[].class, true, true); + } + + VirtualFrame frame = createFrame(getRootNode().getFrameDescriptor(), args); + Object result = callProxy(frame); + + // Profile call return type + if (profiledReturnTypeAssumption == null) { + if (TruffleReturnTypeSpeculation.getValue()) { + CompilerDirectives.transferToInterpreter(); + profiledReturnType = (result == null ? null : result.getClass()); + profiledReturnTypeAssumption = Truffle.getRuntime().createAssumption("Profiled Return Type"); + } + } else if (profiledReturnType != null) { + if (result == null || profiledReturnType != result.getClass()) { + CompilerDirectives.transferToInterpreter(); + profiledReturnType = null; + profiledReturnTypeAssumption.invalidate(); } } + + return result; } - protected abstract void cancelInstalledTask(Node oldNode, Node newNode, CharSequence reason); - - protected abstract void invalidate(Node oldNode, Node newNode, CharSequence reason); - - public final Object executeHelper(Object[] args) { - VirtualFrame frame = createFrame(getRootNode().getFrameDescriptor(), args); - return callProxy(frame); + private static Object castArrayFixedLength(Object[] args, @SuppressWarnings("unused") int length) { + return args; } public static FrameWithoutBoxing createFrame(FrameDescriptor descriptor, Object[] args) { return new FrameWithoutBoxing(descriptor, args); } - public static FrameWithoutBoxing createMaterializedFrame(FrameDescriptor descriptor, Object[] args) { - return new FrameWithoutBoxing(descriptor, args); - } - @Override public void reportLoopCount(int count) { compilationProfile.reportLoopCount(count); @@ -184,242 +308,11 @@ invalidate(oldNode, newNode, reason); } - public abstract SpeculationLog getSpeculationLog(); - public Map getDebugProperties() { Map properties = new LinkedHashMap<>(); - addASTSizeProperty(getInliningResult(), new TruffleCallPath(this), properties); + addASTSizeProperty(this, properties); properties.putAll(getCompilationProfile().getDebugProperties()); return properties; } - - private static void logInliningDecision(OptimizedCallTarget target, TruffleInliningResult result, TruffleInliningHandler handler) { - if (!TraceTruffleInlining.getValue()) { - return; - } - - List profiles = handler.lookupProfiles(result, new TruffleCallPath(target)); - - Collections.sort(profiles); // sorts by hierarchy and source section - - logInliningStart(target); - for (TruffleInliningProfile profile : profiles) { - TruffleCallPath path = profile.getCallPath(); - if (path.getRootCallTarget() == target) { - String msg = result.isInlined(path) ? "inline success" : "inline failed"; - logInlinedImpl(msg, result, handler.getProfiles().get(path), path); - } - } - logInliningDone(target); - } - - private static void logInlinedImpl(String status, TruffleInliningResult result, TruffleInliningProfile profile, TruffleCallPath path) { - Map properties = new LinkedHashMap<>(); - addASTSizeProperty(result, path, properties); - if (profile != null) { - properties.putAll(profile.getDebugProperties()); - } - log((path.getDepth() * 2), status, path.getCallTarget().toString(), properties); - } - - private static void logInliningStart(OptimizedCallTarget target) { - if (TraceTruffleInlining.getValue()) { - log(0, "inline start", target.toString(), target.getDebugProperties()); - } - } - - private static void logInliningDone(OptimizedCallTarget target) { - if (TraceTruffleInlining.getValue()) { - log(0, "inline done", target.toString(), target.getDebugProperties()); - } - } - - protected static void logOptimizingQueued(OptimizedCallTarget target) { - if (TraceTruffleCompilationDetails.getValue()) { - log(0, "opt queued", target.toString(), target.getDebugProperties()); - } - } - - protected static void logOptimizingUnqueued(OptimizedCallTarget target, Node oldNode, Node newNode, CharSequence reason) { - if (TraceTruffleCompilationDetails.getValue()) { - Map properties = new LinkedHashMap<>(); - addReplaceProperties(properties, oldNode, newNode); - properties.put("Reason", reason); - log(0, "opt unqueued", target.toString(), properties); - } - } - - private static void addReplaceProperties(Map properties, Node oldNode, Node newNode) { - if (oldNode != null && newNode != null) { - properties.put("OldClass", oldNode.getClass().getSimpleName()); - properties.put("NewClass", newNode.getClass().getSimpleName()); - properties.put("Node", newNode); - } - } - - static void logOptimizingStart(OptimizedCallTarget target) { - if (TraceTruffleCompilationDetails.getValue()) { - log(0, "opt start", target.toString(), target.getDebugProperties()); - } - } - - protected static void logOptimizedInvalidated(OptimizedCallTarget target, Node oldNode, Node newNode, CharSequence reason) { - if (TraceTruffleCompilation.getValue()) { - Map properties = new LinkedHashMap<>(); - addReplaceProperties(properties, oldNode, newNode); - properties.put("Reason", reason); - log(0, "opt invalidated", target.toString(), properties); - } - } - - protected static void logOptimizingFailed(OptimizedCallTarget callSite, CharSequence reason) { - Map properties = new LinkedHashMap<>(); - properties.put("Reason", reason); - log(0, "opt fail", callSite.toString(), properties); - } - - static void logOptimizingDone(OptimizedCallTarget target, Map properties) { - if (TraceTruffleCompilationDetails.getValue() || TraceTruffleCompilation.getValue()) { - log(0, "opt done", target.toString(), properties); - } - if (TraceTruffleCompilationPolymorphism.getValue()) { - - target.getRootNode().accept(new NodeVisitor() { - public boolean visit(Node node) { - NodeCost kind = node.getCost(); - if (kind == NodeCost.POLYMORPHIC || kind == NodeCost.MEGAMORPHIC) { - Map props = new LinkedHashMap<>(); - props.put("simpleName", node.getClass().getSimpleName()); - String msg = kind == NodeCost.MEGAMORPHIC ? "megamorphic" : "polymorphic"; - log(0, msg, node.toString(), props); - } - if (node instanceof CallNode) { - CallNode callNode = (CallNode) node; - if (callNode.isInlined()) { - callNode.getCurrentRootNode().accept(this); - } - } - return true; - } - }); - - } - } - - private static int splitCount = 0; - - static void logSplit(OptimizedCallNode callNode, OptimizedCallTarget target, OptimizedCallTarget newTarget) { - if (TraceTruffleSplitting.getValue()) { - Map properties = new LinkedHashMap<>(); - addASTSizeProperty(target.getInliningResult(), new TruffleCallPath(target), properties); - properties.put("Split#", ++splitCount); - properties.put("Source", callNode.getEncapsulatingSourceSection()); - log(0, "split", newTarget.toString(), properties); - } - } - - static void addASTSizeProperty(TruffleInliningResult inliningResult, TruffleCallPath countedPath, Map properties) { - int polymorphicCount = OptimizedCallUtils.countNodes(inliningResult, countedPath, new InlinedNodeCountFilter() { - public boolean isCounted(TruffleCallPath path, Node node) { - return node.getCost() == NodeCost.POLYMORPHIC; - } - }); - - int megamorphicCount = OptimizedCallUtils.countNodes(inliningResult, countedPath, new InlinedNodeCountFilter() { - public boolean isCounted(TruffleCallPath path, Node node) { - return node.getCost() == NodeCost.MEGAMORPHIC; - } - }); - - String value = String.format("%4d (%d/%d)", OptimizedCallUtils.countNonTrivialNodes(inliningResult, countedPath), polymorphicCount, megamorphicCount); - properties.put("ASTSize", value); - } - - static void log(int indent, String msg, String details, Map properties) { - StringBuilder sb = new StringBuilder(); - sb.append(String.format("[truffle] %-16s ", msg)); - for (int i = 0; i < indent; i++) { - sb.append(' '); - } - sb.append(String.format("%-" + (60 - indent) + "s", details)); - if (properties != null) { - for (String property : properties.keySet()) { - Object value = properties.get(property); - if (value == null) { - continue; - } - sb.append('|'); - sb.append(property); - - StringBuilder propertyBuilder = new StringBuilder(); - if (value instanceof Integer) { - propertyBuilder.append(String.format("%6d", value)); - } else if (value instanceof Double) { - propertyBuilder.append(String.format("%8.2f", value)); - } else { - propertyBuilder.append(value); - } - - int length = Math.max(1, 20 - property.length()); - sb.append(String.format(" %" + length + "s ", propertyBuilder.toString())); - } - } - OUT.println(sb.toString()); - } - - private static void printProfiling() { - List sortedCallTargets = new ArrayList<>(OptimizedCallTarget.callTargets.keySet()); - Collections.sort(sortedCallTargets, new Comparator() { - - @Override - public int compare(OptimizedCallTarget o1, OptimizedCallTarget o2) { - return o2.callCount - o1.callCount; - } - }); - - int totalCallCount = 0; - int totalInlinedCallSiteCount = 0; - int totalNodeCount = 0; - int totalInvalidationCount = 0; - - OUT.println(); - OUT.printf("%-50s | %-10s | %s / %s | %s | %s\n", "Call Target", "Call Count", "Calls Sites Inlined", "Not Inlined", "Node Count", "Inv"); - for (OptimizedCallTarget callTarget : sortedCallTargets) { - if (callTarget.callCount == 0) { - continue; - } - - int nodeCount = OptimizedCallUtils.countNonTrivialNodes(callTarget.getInliningResult(), new TruffleCallPath(callTarget)); - String comment = callTarget.installedCode == null ? " int" : ""; - comment += callTarget.compilationEnabled ? "" : " fail"; - OUT.printf("%-50s | %10d | %15d | %10d | %3d%s\n", callTarget.getRootNode(), callTarget.callCount, nodeCount, nodeCount, callTarget.getCompilationProfile().getInvalidationCount(), comment); - - totalCallCount += callTarget.callCount; - totalInlinedCallSiteCount += nodeCount; - totalNodeCount += nodeCount; - totalInvalidationCount += callTarget.getCompilationProfile().getInvalidationCount(); - } - OUT.printf("%-50s | %10d | %15d | %10d | %3d\n", "Total", totalCallCount, totalInlinedCallSiteCount, totalNodeCount, totalInvalidationCount); - } - - private static void registerCallTarget(OptimizedCallTarget callTarget) { - callTargets.put(callTarget, 0); - } - - private static Map callTargets; - static { - if (TruffleCallTargetProfiling.getValue()) { - callTargets = new WeakHashMap<>(); - - Runtime.getRuntime().addShutdownHook(new Thread() { - - @Override - public void run() { - printProfiling(); - } - }); - } - } - } diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/OptimizedCallTargetLog.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/OptimizedCallTargetLog.java Mon Apr 28 11:18:15 2014 +0200 @@ -0,0 +1,284 @@ +/* + * 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.truffle; + +import static com.oracle.graal.truffle.TruffleCompilerOptions.*; + +import java.io.*; +import java.util.*; + +import com.oracle.graal.debug.*; +import com.oracle.truffle.api.nodes.*; +import com.oracle.truffle.api.nodes.NodeUtil.NodeCountFilter; + +public final class OptimizedCallTargetLog { + + protected static final PrintStream OUT = TTY.out().out(); + + private static Map callTargets; + static { + if (TruffleCallTargetProfiling.getValue()) { + callTargets = new WeakHashMap<>(); + + Runtime.getRuntime().addShutdownHook(new Thread() { + + @Override + public void run() { + printProfiling(); + } + }); + } + } + + private OptimizedCallTargetLog() { + } + + public static void logInliningDecision(TruffleInliningResult result) { + if (!TraceTruffleInlining.getValue()) { + return; + } + + logInliningStart(result.getCallTarget()); + logInliningDecisionRecursive(result, 0); + logInliningDone(result.getCallTarget()); + } + + private static void logInliningDecisionRecursive(TruffleInliningResult result, int depth) { + List callNodes = searchCallNodes(result.getCallTarget()); + for (OptimizedDirectCallNode callNode : callNodes) { + TruffleInliningProfile profile = result.getProfiles().get(callNode); + boolean inlined = result.isInlined(callNode); + String msg = inlined ? "inline success" : "inline failed"; + logInlinedImpl(msg, callNode, profile, depth); + if (profile.getRecursiveResult() != null && inlined) { + logInliningDecisionRecursive(profile.getRecursiveResult(), depth + 1); + } + } + } + + private static List searchCallNodes(final OptimizedCallTarget target) { + final List callNodes = new ArrayList<>(); + target.getRootNode().accept(new NodeVisitor() { + public boolean visit(Node node) { + if (node instanceof OptimizedDirectCallNode) { + callNodes.add((OptimizedDirectCallNode) node); + } + return true; + } + }); + return callNodes; + } + + private static void logInlinedImpl(String status, OptimizedDirectCallNode callNode, TruffleInliningProfile profile, int depth) { + Map properties = new LinkedHashMap<>(); + addASTSizeProperty(callNode.getCurrentCallTarget(), properties); + if (profile != null) { + properties.putAll(profile.getDebugProperties()); + } + log((depth * 2), status, callNode.getCurrentCallTarget().toString(), properties); + } + + private static void logInliningStart(OptimizedCallTarget target) { + if (TraceTruffleInlining.getValue()) { + log(0, "inline start", target.toString(), target.getDebugProperties()); + } + } + + private static void logInliningDone(OptimizedCallTarget target) { + if (TraceTruffleInlining.getValue()) { + log(0, "inline done", target.toString(), target.getDebugProperties()); + } + } + + public static void logOptimizingQueued(OptimizedCallTarget target) { + if (TraceTruffleCompilationDetails.getValue()) { + log(0, "opt queued", target.toString(), target.getDebugProperties()); + } + } + + public static void logOptimizingUnqueued(OptimizedCallTarget target, Node oldNode, Node newNode, CharSequence reason) { + if (TraceTruffleCompilationDetails.getValue()) { + Map properties = new LinkedHashMap<>(); + addReplaceProperties(properties, oldNode, newNode); + properties.put("Reason", reason); + log(0, "opt unqueued", target.toString(), properties); + } + } + + private static void addReplaceProperties(Map properties, Node oldNode, Node newNode) { + if (oldNode != null && newNode != null) { + properties.put("OldClass", oldNode.getClass().getSimpleName()); + properties.put("NewClass", newNode.getClass().getSimpleName()); + properties.put("Node", newNode); + } + } + + static void logOptimizingStart(OptimizedCallTarget target) { + if (TraceTruffleCompilationDetails.getValue()) { + log(0, "opt start", target.toString(), target.getDebugProperties()); + } + } + + public static void logOptimizedInvalidated(OptimizedCallTarget target, Node oldNode, Node newNode, CharSequence reason) { + if (TraceTruffleCompilation.getValue()) { + Map properties = new LinkedHashMap<>(); + addReplaceProperties(properties, oldNode, newNode); + properties.put("Reason", reason); + log(0, "opt invalidated", target.toString(), properties); + } + } + + public static void logOptimizingFailed(OptimizedCallTarget callSite, CharSequence reason) { + Map properties = new LinkedHashMap<>(); + properties.put("Reason", reason); + log(0, "opt fail", callSite.toString(), properties); + } + + static void logOptimizingDone(OptimizedCallTarget target, Map properties) { + if (TraceTruffleCompilationDetails.getValue() || TraceTruffleCompilation.getValue()) { + log(0, "opt done", target.toString(), properties); + } + if (TraceTruffleCompilationPolymorphism.getValue()) { + + target.getRootNode().accept(new NodeVisitor() { + public boolean visit(Node node) { + NodeCost kind = node.getCost(); + if (kind == NodeCost.POLYMORPHIC || kind == NodeCost.MEGAMORPHIC) { + Map props = new LinkedHashMap<>(); + props.put("simpleName", node.getClass().getSimpleName()); + String msg = kind == NodeCost.MEGAMORPHIC ? "megamorphic" : "polymorphic"; + log(0, msg, node.toString(), props); + } + if (node instanceof DirectCallNode) { + DirectCallNode callNode = (DirectCallNode) node; + if (callNode.isInlined()) { + callNode.getCurrentRootNode().accept(this); + } + } + return true; + } + }); + + } + } + + private static int splitCount = 0; + + static void logSplit(OptimizedDirectCallNode callNode, OptimizedCallTarget target, OptimizedCallTarget newTarget) { + if (TraceTruffleSplitting.getValue()) { + Map properties = new LinkedHashMap<>(); + addASTSizeProperty(target, properties); + properties.put("Split#", ++splitCount); + properties.put("Source", callNode.getEncapsulatingSourceSection()); + log(0, "split", newTarget.toString(), properties); + } + } + + static void addASTSizeProperty(OptimizedCallTarget target, Map properties) { + int polymorphicCount = NodeUtil.countNodes(target.getRootNode(), new NodeCountFilter() { + public boolean isCounted(Node node) { + return node.getCost() == NodeCost.POLYMORPHIC; + } + }, true); + + int megamorphicCount = NodeUtil.countNodes(target.getRootNode(), new NodeCountFilter() { + public boolean isCounted(Node node) { + return node.getCost() == NodeCost.MEGAMORPHIC; + } + }, true); + + String value = String.format("%4d (%d/%d)", OptimizedCallUtils.countNonTrivialNodes(target, true), polymorphicCount, megamorphicCount); + properties.put("ASTSize", value); + } + + static void log(int indent, String msg, String details, Map properties) { + StringBuilder sb = new StringBuilder(); + sb.append(String.format("[truffle] %-16s ", msg)); + for (int i = 0; i < indent; i++) { + sb.append(' '); + } + sb.append(String.format("%-" + (60 - indent) + "s", details)); + if (properties != null) { + for (String property : properties.keySet()) { + Object value = properties.get(property); + if (value == null) { + continue; + } + sb.append('|'); + sb.append(property); + + StringBuilder propertyBuilder = new StringBuilder(); + if (value instanceof Integer) { + propertyBuilder.append(String.format("%6d", value)); + } else if (value instanceof Double) { + propertyBuilder.append(String.format("%8.2f", value)); + } else { + propertyBuilder.append(value); + } + + int length = Math.max(1, 20 - property.length()); + sb.append(String.format(" %" + length + "s ", propertyBuilder.toString())); + } + } + OUT.println(sb.toString()); + } + + private static void printProfiling() { + List sortedCallTargets = new ArrayList<>(callTargets.keySet()); + Collections.sort(sortedCallTargets, new Comparator() { + + @Override + public int compare(OptimizedCallTarget o1, OptimizedCallTarget o2) { + return o2.callCount - o1.callCount; + } + }); + + int totalCallCount = 0; + int totalInlinedCallSiteCount = 0; + int totalNodeCount = 0; + int totalInvalidationCount = 0; + + OUT.println(); + OUT.printf("%-50s | %-10s | %s / %s | %s | %s\n", "Call Target", "Call Count", "Calls Sites Inlined", "Not Inlined", "Node Count", "Inv"); + for (OptimizedCallTarget callTarget : sortedCallTargets) { + if (callTarget.callCount == 0) { + continue; + } + + int nodeCount = OptimizedCallUtils.countNonTrivialNodes(callTarget, true); + String comment = callTarget.isValid() ? "" : " int"; + OUT.printf("%-50s | %10d | %15d | %10d | %3d%s\n", callTarget.getRootNode(), callTarget.callCount, nodeCount, nodeCount, callTarget.getCompilationProfile().getInvalidationCount(), comment); + + totalCallCount += callTarget.callCount; + totalInlinedCallSiteCount += nodeCount; + totalNodeCount += nodeCount; + totalInvalidationCount += callTarget.getCompilationProfile().getInvalidationCount(); + } + OUT.printf("%-50s | %10d | %15d | %10d | %3d\n", "Total", totalCallCount, totalInlinedCallSiteCount, totalNodeCount, totalInvalidationCount); + } + + public static void registerCallTarget(OptimizedCallTarget callTarget) { + callTargets.put(callTarget, 0); + } + +} diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/OptimizedCallUtils.java --- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/OptimizedCallUtils.java Fri Apr 25 16:21:07 2014 +0200 +++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/OptimizedCallUtils.java Mon Apr 28 11:18:15 2014 +0200 @@ -23,98 +23,35 @@ package com.oracle.graal.truffle; import com.oracle.truffle.api.nodes.*; +import com.oracle.truffle.api.nodes.NodeUtil.NodeCountFilter; class OptimizedCallUtils { - public abstract static class InlinedCallVisitor implements NodeVisitor { - - private TruffleCallPath currentPath; - private final TruffleInliningResult inliningDecision; - - public InlinedCallVisitor(TruffleInliningResult inliningDecision, TruffleCallPath initialPath) { - this.inliningDecision = inliningDecision; - this.currentPath = initialPath; - } - - public final TruffleInliningResult getInliningDecision() { - return inliningDecision; - } - - public final boolean visit(Node node) { - if (node instanceof OptimizedCallNode) { - OptimizedCallNode callNode = ((OptimizedCallNode) node); - this.currentPath = new TruffleCallPath(this.currentPath, callNode); - try { - boolean result = visit(currentPath, node); - TruffleInliningResult decision = inliningDecision; - if (decision != null && decision.isInlined(currentPath)) { - callNode.getCurrentRootNode().accept(this); - } - return result; - } finally { - this.currentPath = this.currentPath.getParent(); - } - } else { - return visit(currentPath, node); + public static int countCalls(OptimizedCallTarget target) { + return NodeUtil.countNodes(target.getRootNode(), new NodeCountFilter() { + public boolean isCounted(Node node) { + return node instanceof DirectCallNode; } - } - - public abstract boolean visit(TruffleCallPath path, Node node); - + }, true); } - public static int countNodes(TruffleInliningResult decision, TruffleCallPath path, InlinedNodeCountFilter filter) { - InlinedNodeCountVisitor nodeCount = new InlinedNodeCountVisitor(decision, path, filter); - path.getCallTarget().getRootNode().accept(nodeCount); - return nodeCount.nodeCount; - } - - public static int countCalls(TruffleInliningResult decision, TruffleCallPath path) { - InlinedNodeCountVisitor nodeCount = new InlinedNodeCountVisitor(decision, path, new InlinedNodeCountFilter() { - public boolean isCounted(TruffleCallPath p, Node node) { - return node instanceof CallNode; + public static int countCallsInlined(OptimizedCallTarget target) { + return NodeUtil.countNodes(target.getRootNode(), new NodeCountFilter() { + public boolean isCounted(Node node) { + return (node instanceof OptimizedDirectCallNode) && ((OptimizedDirectCallNode) node).isInlined(); } - }); - path.getCallTarget().getRootNode().accept(nodeCount); - return nodeCount.nodeCount; - } - - public interface InlinedNodeCountFilter { - - boolean isCounted(TruffleCallPath path, Node node); + }, true); } - private static final class InlinedNodeCountVisitor extends InlinedCallVisitor { - - private final InlinedNodeCountFilter filter; - int nodeCount; - - private InlinedNodeCountVisitor(TruffleInliningResult decision, TruffleCallPath initialPath, InlinedNodeCountFilter filter) { - super(decision, initialPath); - this.filter = filter; - } - - @Override - public boolean visit(TruffleCallPath path, Node node) { - if (filter == null || filter.isCounted(path, node)) { - nodeCount++; - } - return true; - } - - } - - static int countNonTrivialNodes(TruffleInliningResult state, TruffleCallPath path) { - return countNodes(state, path, new InlinedNodeCountFilter() { - - public boolean isCounted(TruffleCallPath p, Node node) { + public static int countNonTrivialNodes(final OptimizedCallTarget target, final boolean inlined) { + return NodeUtil.countNodes(target.getRootNode(), new NodeCountFilter() { + public boolean isCounted(Node node) { NodeCost cost = node.getCost(); if (cost != null && cost != NodeCost.NONE && cost != NodeCost.UNINITIALIZED) { return true; } return false; } - }); + }, inlined); } - } diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/OptimizedDirectCallNode.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/OptimizedDirectCallNode.java Mon Apr 28 11:18:15 2014 +0200 @@ -0,0 +1,222 @@ +/* + * 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.truffle; + +import com.oracle.truffle.api.*; +import com.oracle.truffle.api.CompilerDirectives.CompilationFinal; +import com.oracle.truffle.api.frame.FrameInstance.FrameAccess; +import com.oracle.truffle.api.frame.*; +import com.oracle.truffle.api.nodes.*; +import com.oracle.truffle.api.nodes.NodeUtil.NodeCountFilter; + +/** + * A call node with a constant {@link CallTarget} that can be optimized by Graal. + */ +public final class OptimizedDirectCallNode extends DirectCallNode implements MaterializedFrameNotify { + + private int callCount; + private boolean trySplit = true; + private boolean inliningForced; + + @CompilationFinal private boolean inlined; + @CompilationFinal private OptimizedCallTarget splitCallTarget; + @CompilationFinal private FrameAccess outsideFrameAccess = FrameAccess.NONE; + + private OptimizedDirectCallNode(OptimizedCallTarget target) { + super(target); + } + + @Override + public Object call(VirtualFrame frame, Object[] arguments) { + if (CompilerDirectives.inInterpreter()) { + onInterpreterCall(); + } + return callProxy(this, getCurrentCallTarget(), frame, arguments, inlined, true); + } + + public static Object callProxy(MaterializedFrameNotify notify, CallTarget callTarget, VirtualFrame frame, Object[] arguments, boolean inlined, boolean direct) { + try { + if (notify.getOutsideFrameAccess() != FrameAccess.NONE) { + CompilerDirectives.materialize(frame); + } + if (inlined) { + return ((OptimizedCallTarget) callTarget).callInlined(arguments); + } else if (direct) { + return ((OptimizedCallTarget) callTarget).callDirect(arguments); + } else { + return callTarget.call(arguments); + } + } finally { + // this assertion is needed to keep the values from being cleared as non-live locals + assert notify != null & callTarget != null & frame != null; + } + } + + @Override + public boolean isInlinable() { + return true; + } + + @Override + public void forceInlining() { + inliningForced = true; + } + + @Override + public boolean isInliningForced() { + return inliningForced; + } + + @Override + public FrameAccess getOutsideFrameAccess() { + return outsideFrameAccess; + } + + @Override + public void setOutsideFrameAccess(FrameAccess outsideFrameAccess) { + this.outsideFrameAccess = outsideFrameAccess; + } + + @Override + public boolean isSplittable() { + return getCallTarget().getRootNode().isSplittable(); + } + + @Override + public OptimizedCallTarget getCallTarget() { + return (OptimizedCallTarget) super.getCallTarget(); + } + + public int getCallCount() { + return callCount; + } + + @Override + public OptimizedCallTarget getCurrentCallTarget() { + return (OptimizedCallTarget) super.getCurrentCallTarget(); + } + + @Override + public OptimizedCallTarget getSplitCallTarget() { + return splitCallTarget; + } + + private void onInterpreterCall() { + callCount++; + if (trySplit) { + if (callCount == 1) { + // on first call + getCurrentCallTarget().incrementKnownCallSites(); + } + if (callCount > 1 && !inlined) { + trySplit = false; + if (shouldSplit()) { + splitImpl(true); + } + } + } + } + + /* Called by the runtime system if this CallNode is really going to be inlined. */ + void inline() { + inlined = true; + } + + @Override + public boolean isInlined() { + return inlined; + } + + @Override + public boolean split() { + splitImpl(false); + return true; + } + + private void splitImpl(boolean heuristic) { + CompilerAsserts.neverPartOfCompilation(); + + OptimizedCallTarget splitTarget = (OptimizedCallTarget) Truffle.getRuntime().createCallTarget(getCallTarget().getRootNode().split()); + splitTarget.setSplitSource(getCallTarget()); + if (heuristic) { + OptimizedCallTargetLog.logSplit(this, getCallTarget(), splitTarget); + } + if (callCount >= 1) { + getCallTarget().decrementKnownCallSites(); + splitTarget.incrementKnownCallSites(); + } + this.splitCallTarget = splitTarget; + } + + private boolean shouldSplit() { + if (splitCallTarget != null) { + return false; + } + if (!TruffleCompilerOptions.TruffleSplittingEnabled.getValue()) { + return false; + } + if (!isSplittable()) { + return false; + } + OptimizedCallTarget splitTarget = getCallTarget(); + int nodeCount = OptimizedCallUtils.countNonTrivialNodes(splitTarget, false); + if (nodeCount > TruffleCompilerOptions.TruffleSplittingMaxCalleeSize.getValue()) { + return false; + } + + // disable recursive splitting for now + OptimizedCallTarget root = (OptimizedCallTarget) getRootNode().getCallTarget(); + if (root == splitTarget || root.getSplitSource() == splitTarget) { + // recursive call found + return false; + } + + // max one child call and callCount > 2 and kind of small number of nodes + if (isMaxSingleCall()) { + return true; + } + return countPolymorphic() >= 1; + } + + private boolean isMaxSingleCall() { + return NodeUtil.countNodes(getCurrentCallTarget().getRootNode(), new NodeCountFilter() { + public boolean isCounted(Node node) { + return node instanceof DirectCallNode; + } + }) <= 1; + } + + private int countPolymorphic() { + return NodeUtil.countNodes(getCurrentCallTarget().getRootNode(), new NodeCountFilter() { + public boolean isCounted(Node node) { + NodeCost cost = node.getCost(); + boolean polymorphic = cost == NodeCost.POLYMORPHIC || cost == NodeCost.MEGAMORPHIC; + return polymorphic; + } + }); + } + + public static OptimizedDirectCallNode create(OptimizedCallTarget target) { + return new OptimizedDirectCallNode(target); + } +} diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/OptimizedIndirectCallNode.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/OptimizedIndirectCallNode.java Mon Apr 28 11:18:15 2014 +0200 @@ -0,0 +1,53 @@ +/* + * 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.truffle; + +import com.oracle.truffle.api.*; +import com.oracle.truffle.api.CompilerDirectives.CompilationFinal; +import com.oracle.truffle.api.frame.FrameInstance.FrameAccess; +import com.oracle.truffle.api.frame.*; +import com.oracle.truffle.api.nodes.*; + +/** + * A call node with a constant {@link CallTarget} that can be optimized by Graal. + */ +public final class OptimizedIndirectCallNode extends IndirectCallNode implements MaterializedFrameNotify { + + @CompilationFinal private FrameAccess outsideFrameAccess = FrameAccess.NONE; + + @Override + public Object call(VirtualFrame frame, CallTarget target, Object[] arguments) { + return OptimizedDirectCallNode.callProxy(this, target, frame, arguments, false, false); + } + + @Override + public FrameAccess getOutsideFrameAccess() { + return outsideFrameAccess; + } + + @Override + public void setOutsideFrameAccess(FrameAccess outsideFrameAccess) { + this.outsideFrameAccess = outsideFrameAccess; + } + +} diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/PartialEvaluator.java --- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/PartialEvaluator.java Fri Apr 25 16:21:07 2014 +0200 +++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/PartialEvaluator.java Mon Apr 28 11:18:15 2014 +0200 @@ -22,10 +22,9 @@ */ package com.oracle.graal.truffle; -import static com.oracle.graal.phases.GraalOptions.*; +import static com.oracle.graal.compiler.common.GraalOptions.*; import static com.oracle.graal.truffle.TruffleCompilerOptions.*; -import java.lang.reflect.*; import java.util.*; import com.oracle.graal.api.code.*; @@ -35,8 +34,8 @@ import com.oracle.graal.debug.*; import com.oracle.graal.debug.Debug.Scope; import com.oracle.graal.debug.internal.*; +import com.oracle.graal.graph.Graph.Mark; import com.oracle.graal.graph.*; -import com.oracle.graal.graph.Graph.Mark; import com.oracle.graal.graph.Node; import com.oracle.graal.graph.spi.*; import com.oracle.graal.loop.*; @@ -44,7 +43,6 @@ import com.oracle.graal.nodes.java.*; import com.oracle.graal.nodes.java.MethodCallTargetNode.InvokeKind; import com.oracle.graal.nodes.spi.*; -import com.oracle.graal.nodes.type.*; import com.oracle.graal.nodes.util.*; import com.oracle.graal.nodes.virtual.*; import com.oracle.graal.phases.*; @@ -69,14 +67,12 @@ private final CanonicalizerPhase canonicalizer; private Set constantReceivers; private final TruffleCache truffleCache; - private final ResolvedJavaType frameType; public PartialEvaluator(Providers providers, TruffleCache truffleCache) { this.providers = providers; CustomCanonicalizer customCanonicalizer = new PartialEvaluatorCanonicalizer(providers.getMetaAccess(), providers.getConstantReflection()); this.canonicalizer = new CanonicalizerPhase(!ImmutableCode.getValue(), customCanonicalizer); this.truffleCache = truffleCache; - this.frameType = providers.getMetaAccess().lookupJavaType(FrameWithoutBoxing.class); } public StructuredGraph createGraph(final OptimizedCallTarget callTarget, final Assumptions assumptions) { @@ -86,11 +82,11 @@ throw Debug.handle(e); } - if (TraceTruffleCompilationHistogram.getValue()) { + if (TraceTruffleCompilationHistogram.getValue() || TraceTruffleCompilationDetails.getValue()) { constantReceivers = new HashSet<>(); } - final StructuredGraph graph = truffleCache.createRootGraph(); + final StructuredGraph graph = truffleCache.createRootGraph(callTarget.toString()); assert graph != null : "no graph for root method"; try (Scope s = Debug.scope("CreateGraph", graph); Indent indent = Debug.logAndIndent("createGraph %s", graph.method())) { @@ -113,15 +109,10 @@ // Intrinsify methods. new ReplaceIntrinsicsPhase(providers.getReplacements()).apply(graph); - NewFrameNode newFrameNode = graph.getNodes(NewFrameNode.class).first(); - if (newFrameNode == null) { - throw GraalInternalError.shouldNotReachHere("frame not found"); - } - Debug.dump(graph, "Before inlining"); // Make sure frame does not escape. - expandTree(callTarget, graph, assumptions); + expandTree(graph, assumptions); if (Thread.currentThread().isInterrupted()) { return null; @@ -132,7 +123,16 @@ if (TraceTruffleCompilationHistogram.getValue() && constantReceivers != null) { DebugHistogram histogram = Debug.createHistogram("Expanded Truffle Nodes"); for (Constant c : constantReceivers) { - histogram.add(providers.getMetaAccess().lookupJavaType(c).getName()); + String javaName = MetaUtil.toJavaName(providers.getMetaAccess().lookupJavaType(c), false); + + // The DSL uses nested classes with redundant names - only show the inner class + int index = javaName.indexOf('$'); + if (index != -1) { + javaName = javaName.substring(index + 1); + } + + histogram.add(javaName); + } new DebugHistogramAsciiPrinter(TTY.out().out()).print(histogram); } @@ -175,25 +175,23 @@ return graph; } - private void expandTree(OptimizedCallTarget target, StructuredGraph graph, Assumptions assumptions) { + private void expandTree(StructuredGraph graph, Assumptions assumptions) { PhaseContext phaseContext = new PhaseContext(providers, assumptions); TruffleExpansionLogger expansionLogger = null; if (TraceTruffleExpansion.getValue()) { expansionLogger = new TruffleExpansionLogger(providers, graph); } - boolean inliningEnabled = target.getInliningResult() != null && target.getInliningResult().size() > 0; - Map methodTargetToStack = new HashMap<>(); boolean changed; do { changed = false; for (MethodCallTargetNode methodCallTargetNode : graph.getNodes(MethodCallTargetNode.class)) { InvokeKind kind = methodCallTargetNode.invokeKind(); try (Indent id1 = Debug.logAndIndent("try inlining %s, kind = %s", methodCallTargetNode.targetMethod(), kind)) { - if (kind == InvokeKind.Static || (kind == InvokeKind.Special && (methodCallTargetNode.receiver().isConstant() || isFrame(methodCallTargetNode.receiver())))) { - if (TraceTruffleCompilationHistogram.getValue() && kind == InvokeKind.Special) { - ConstantNode constantNode = (ConstantNode) methodCallTargetNode.arguments().first(); - constantReceivers.add(constantNode.asConstant()); + if (kind == InvokeKind.Static || kind == InvokeKind.Special) { + if ((TraceTruffleCompilationHistogram.getValue() || TraceTruffleCompilationDetails.getValue()) && kind == InvokeKind.Special && methodCallTargetNode.receiver().isConstant()) { + constantReceivers.add(methodCallTargetNode.receiver().asConstant()); } + Replacements replacements = providers.getReplacements(); Class macroSubstitution = replacements.getMacroSubstitution(methodCallTargetNode.targetMethod()); if (macroSubstitution != null) { @@ -202,41 +200,25 @@ continue; } - if (TraceTruffleCompilationDetails.getValue() && kind == InvokeKind.Special) { - ConstantNode constantNode = (ConstantNode) methodCallTargetNode.arguments().first(); - constantReceivers.add(constantNode.asConstant()); - } - StructuredGraph inlineGraph = replacements.getMethodSubstitution(methodCallTargetNode.targetMethod()); - if (inliningEnabled && inlineGraph == null) { - inlineGraph = expandInlinableCallNode(target, methodTargetToStack, assumptions, phaseContext, methodCallTargetNode); - } - - if (inlineGraph == null && !Modifier.isNative(methodCallTargetNode.targetMethod().getModifiers())) { + if (inlineGraph == null && !methodCallTargetNode.targetMethod().isNative() && methodCallTargetNode.targetMethod().canBeInlined()) { inlineGraph = parseGraph(methodCallTargetNode.targetMethod(), methodCallTargetNode.arguments(), assumptions, phaseContext, false); } if (inlineGraph != null) { try (Indent indent = Debug.logAndIndent("inline graph %s", methodCallTargetNode.targetMethod())) { - if (inliningEnabled) { - preExpandTruffleCallPath(inlineGraph, methodTargetToStack, methodTargetToStack.get(methodCallTargetNode)); - } + int nodeCountBefore = graph.getNodeCount(); Mark mark = graph.getMark(); if (TraceTruffleExpansion.getValue()) { expansionLogger.preExpand(methodCallTargetNode, inlineGraph); } List invokeUsages = methodCallTargetNode.invoke().asNode().usages().snapshot(); - // try (Indent in2 = Debug.logAndIndent(false, "do inlining")) { Map inlined = InliningUtil.inline(methodCallTargetNode.invoke(), inlineGraph, false); if (TraceTruffleExpansion.getValue()) { expansionLogger.postExpand(inlined); } - if (inliningEnabled) { - postExpandTruffleCallPath(methodTargetToStack, inlined); - } if (Debug.isDumpEnabled()) { - Debug.log("dump enabled"); int nodeCountAfter = graph.getNodeCount(); Debug.dump(graph, "After inlining %s %+d (%d)", methodCallTargetNode.targetMethod().toString(), nodeCountAfter - nodeCountBefore, nodeCountAfter); } @@ -259,79 +241,6 @@ } } - private static void preExpandTruffleCallPath(StructuredGraph inlineGraph, Map methodTargetToCallPath, TruffleCallPath truffleCallPath) { - for (MethodCallTargetNode methodTargetNode : inlineGraph.getNodes(MethodCallTargetNode.class)) { - methodTargetToCallPath.put(methodTargetNode, truffleCallPath); - } - } - - private static void postExpandTruffleCallPath(Map methodCallTargetToCallPath, Map nodeUpdates) { - for (Object key : methodCallTargetToCallPath.keySet().toArray()) { - if (nodeUpdates.containsKey(key)) { - methodCallTargetToCallPath.put(nodeUpdates.get(key), methodCallTargetToCallPath.get(key)); - methodCallTargetToCallPath.remove(key); - } - } - } - - private StructuredGraph expandInlinableCallNode(OptimizedCallTarget target, Map methodCallToCallPath, Assumptions assumptions, PhaseContext phaseContext, - MethodCallTargetNode methodCallTargetNode) { - - ValueNode receiverNode = methodCallTargetNode.receiver(); - if (receiverNode == null || !receiverNode.isConstant() || !receiverNode.asConstant().getKind().isObject()) { - return null; - } - - ResolvedJavaMethod method = methodCallTargetNode.targetMethod(); - if (!method.getName().equals("call") || method.getSignature().getParameterCount(false) != 1) { - return null; - } - - /* - * Accessing the constant using the SnippetReflectionProvider is a workaround, we should - * think about a better solution. Since object constants are VM-specific, only the hosting - * VM knows how to do the conversion. - */ - SnippetReflectionProvider snippetReflection = Graal.getRequiredCapability(SnippetReflectionProvider.class); - Object receiverValue = snippetReflection.asObject(receiverNode.asConstant()); - if (receiverValue instanceof OptimizedCallNode) { - OptimizedCallNode callNode = (OptimizedCallNode) receiverValue; - TruffleCallPath callPath = methodCallToCallPath.get(methodCallTargetNode); - if (callPath == null) { - callPath = new TruffleCallPath(target); - } - callPath = new TruffleCallPath(callPath, callNode); - methodCallToCallPath.put(methodCallTargetNode, callPath); - // let the normal expansion do the work - return null; - } else if (receiverValue instanceof OptimizedCallTarget) { - TruffleCallPath path = methodCallToCallPath.get(methodCallTargetNode); - // path unknown. direct call to OptimizedCallTarget without OptimizedCallNode? - if (path == null) { - return null; - } - - TruffleInliningResult decision = target.getInliningResult(); - if (decision == null) { // no inlining decision. inlining disabled? - return null; - } - - if (!decision.isInlined(path)) { - // the OptimizedCallTarget has decided not to inline this call path - return null; - } - - // inline truffle call - return parseGraph(methodCallTargetNode.targetMethod(), methodCallTargetNode.arguments(), assumptions, phaseContext, true); - } - - return null; - } - - private boolean isFrame(ValueNode receiver) { - return receiver instanceof NewFrameNode || Objects.equals(ObjectStamp.typeOrNull(receiver.stamp()), frameType); - } - private StructuredGraph parseGraph(final ResolvedJavaMethod targetMethod, final NodeInputList arguments, final Assumptions assumptions, final PhaseContext phaseContext, boolean ignoreSlowPath) { diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/PartialEvaluatorCanonicalizer.java --- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/PartialEvaluatorCanonicalizer.java Fri Apr 25 16:21:07 2014 +0200 +++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/PartialEvaluatorCanonicalizer.java Mon Apr 28 11:18:15 2014 +0200 @@ -22,8 +22,6 @@ */ package com.oracle.graal.truffle; -import java.lang.reflect.*; - import com.oracle.graal.api.meta.*; import com.oracle.graal.graph.Node; import com.oracle.graal.nodes.*; @@ -47,7 +45,7 @@ if (node instanceof LoadFieldNode) { LoadFieldNode loadFieldNode = (LoadFieldNode) node; if (!loadFieldNode.isStatic() && loadFieldNode.object().isConstant() && !loadFieldNode.object().isNullConstant()) { - if (Modifier.isFinal(loadFieldNode.field().getModifiers()) || (loadFieldNode.getKind() == Kind.Object && loadFieldNode.field().getAnnotation(Child.class) != null) || + if (loadFieldNode.field().isFinal() || (loadFieldNode.getKind() == Kind.Object && loadFieldNode.field().getAnnotation(Child.class) != null) || loadFieldNode.field().getAnnotation(CompilerDirectives.CompilationFinal.class) != null) { Constant constant = loadFieldNode.field().readValue(loadFieldNode.object().asConstant()); assert verifyFieldValue(loadFieldNode.field(), constant); diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/TimedCompilationPolicy.java --- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/TimedCompilationPolicy.java Fri Apr 25 16:21:07 2014 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,51 +0,0 @@ -/* - * 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.truffle; - -import static com.oracle.graal.truffle.TruffleCompilerOptions.*; - -import java.io.*; - -public class TimedCompilationPolicy extends DefaultCompilationPolicy { - - @Override - public boolean shouldCompile(CompilationProfile profile) { - if (super.shouldCompile(profile)) { - long timestamp = System.nanoTime(); - long prevTimestamp = profile.getPreviousTimestamp(); - long timespan = (timestamp - prevTimestamp); - if (timespan < (TruffleCompilationDecisionTime.getValue())) { - return true; - } - // TODO shouldCompile should not modify the compilation profile - // maybe introduce another method? - profile.reportTiminingFailed(timestamp); - if (TruffleCompilationDecisionTimePrintFail.getValue()) { - PrintStream out = System.out; - out.println(profile.getName() + ": timespan " + (timespan / 1000000) + " ms larger than threshold"); - } - } - return false; - } - -} diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/TruffleCache.java --- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/TruffleCache.java Fri Apr 25 16:21:07 2014 +0200 +++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/TruffleCache.java Mon Apr 28 11:18:15 2014 +0200 @@ -31,9 +31,9 @@ public interface TruffleCache { /** - * Creates the graph for the root method, i.e. {@link OptimizedCallTarget#executeHelper}. + * Creates the graph for the root method, i.e. {@link OptimizedCallTarget#callBoundary}. */ - StructuredGraph createRootGraph(); + StructuredGraph createRootGraph(String name); /** * Returns a cached graph for a method with given arguments. diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/TruffleCacheImpl.java --- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/TruffleCacheImpl.java Fri Apr 25 16:21:07 2014 +0200 +++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/TruffleCacheImpl.java Mon Apr 28 11:18:15 2014 +0200 @@ -22,9 +22,8 @@ */ package com.oracle.graal.truffle; -import static com.oracle.graal.phases.GraalOptions.*; +import static com.oracle.graal.compiler.common.GraalOptions.*; -import java.lang.reflect.*; import java.util.*; import java.util.Map.Entry; @@ -65,7 +64,7 @@ private final HashMap, Long> lastUsed = new HashMap<>(); private final StructuredGraph markerGraph = new StructuredGraph(); private final ResolvedJavaType stringBuilderClass; - private final ResolvedJavaMethod executeHelperMethod; + private final ResolvedJavaMethod callBoundaryMethod; private long counter; public TruffleCacheImpl(Providers providers, GraphBuilderConfiguration config, GraphBuilderConfiguration configForRootGraph, OptimisticOptimizations optimisticOptimizations) { @@ -75,14 +74,14 @@ this.optimisticOptimizations = optimisticOptimizations; this.stringBuilderClass = providers.getMetaAccess().lookupJavaType(StringBuilder.class); try { - executeHelperMethod = providers.getMetaAccess().lookupJavaMethod(OptimizedCallTarget.class.getDeclaredMethod("executeHelper", Object[].class)); + callBoundaryMethod = providers.getMetaAccess().lookupJavaMethod(OptimizedCallTarget.class.getDeclaredMethod("callRoot", Object[].class)); } catch (NoSuchMethodException ex) { throw new RuntimeException(ex); } } - public StructuredGraph createRootGraph() { - StructuredGraph graph = new StructuredGraph(executeHelperMethod); + public StructuredGraph createRootGraph(String name) { + StructuredGraph graph = new StructuredGraph(name, callBoundaryMethod); new GraphBuilderPhase.Instance(providers.getMetaAccess(), configForRootGraph, TruffleCompilerImpl.Optimizations).apply(graph); return graph; } @@ -251,7 +250,7 @@ if (methodCallTargetNode.targetMethod().isConstructor()) { ResolvedJavaType runtimeException = providers.getMetaAccess().lookupJavaType(RuntimeException.class); ResolvedJavaType controlFlowException = providers.getMetaAccess().lookupJavaType(ControlFlowException.class); - ResolvedJavaType exceptionType = Objects.requireNonNull(ObjectStamp.typeOrNull(methodCallTargetNode.receiver().stamp())); + ResolvedJavaType exceptionType = Objects.requireNonNull(StampTool.typeOrNull(methodCallTargetNode.receiver().stamp())); if (runtimeException.isAssignableFrom(methodCallTargetNode.targetMethod().getDeclaringClass()) && !controlFlowException.isAssignableFrom(exceptionType)) { DeoptimizeNode deoptNode = methodCallTargetNode.graph().add(new DeoptimizeNode(DeoptimizationAction.InvalidateRecompile, DeoptimizationReason.UnreachedCode)); FixedNode invokeNode = methodCallTargetNode.invoke().asNode(); @@ -264,9 +263,10 @@ } private boolean shouldInline(final MethodCallTargetNode methodCallTargetNode) { - return (methodCallTargetNode.invokeKind() == InvokeKind.Special || methodCallTargetNode.invokeKind() == InvokeKind.Static) && - !Modifier.isNative(methodCallTargetNode.targetMethod().getModifiers()) && methodCallTargetNode.targetMethod().getAnnotation(ExplodeLoop.class) == null && + boolean result = (methodCallTargetNode.invokeKind() == InvokeKind.Special || methodCallTargetNode.invokeKind() == InvokeKind.Static) && methodCallTargetNode.targetMethod().canBeInlined() && + !methodCallTargetNode.targetMethod().isNative() && methodCallTargetNode.targetMethod().getAnnotation(ExplodeLoop.class) == null && methodCallTargetNode.targetMethod().getAnnotation(CompilerDirectives.SlowPath.class) == null && !methodCallTargetNode.targetMethod().getDeclaringClass().equals(stringBuilderClass); + return result; } } diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/TruffleCallBoundary.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/TruffleCallBoundary.java Mon Apr 28 11:18:15 2014 +0200 @@ -0,0 +1,31 @@ +/* + * Copyright (c) 2014, 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.graal.truffle; + +import java.lang.annotation.*; + +@Retention(RetentionPolicy.RUNTIME) +@Target(ElementType.METHOD) +public @interface TruffleCallBoundary { + +} diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/TruffleCallPath.java --- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/TruffleCallPath.java Fri Apr 25 16:21:07 2014 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,219 +0,0 @@ -/* - * 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.truffle; - -import java.util.*; - -import com.oracle.truffle.api.*; - -public final class TruffleCallPath implements Iterable, Comparable { - - private final OptimizedCallNode callNode; - private final TruffleCallPath parent; - private final OptimizedCallTarget rootCallTarget; - - public TruffleCallPath(OptimizedCallTarget parent) { - this.rootCallTarget = Objects.requireNonNull(parent); - this.callNode = null; - this.parent = null; - } - - public TruffleCallPath(TruffleCallPath parent, OptimizedCallNode node) { - this.parent = Objects.requireNonNull(parent); - assert !parent.containsPath(this) : "cyclic path detected"; - this.callNode = Objects.requireNonNull(node); - this.rootCallTarget = parent.getRootCallTarget(); - } - - public boolean isRoot() { - return parent == null && rootCallTarget != null; - } - - private boolean containsPath(TruffleCallPath p) { - return p == this || (getParent() != null && this.getParent().containsPath(p)); - } - - public OptimizedCallTarget getRootCallTarget() { - return rootCallTarget; - } - - @Override - public String toString() { - return (parent != null ? (parent.toString() + " -> ") : "") + getCallTarget().toString(); - } - - public Iterator iterator() { - return toList().iterator(); - } - - public OptimizedCallTarget getCallTarget() { - return parent == null ? rootCallTarget : callNode.getCurrentCallTarget(); - } - - public List toList() { - List list = new ArrayList<>(); - toListImpl(list); - return list; - } - - private void toListImpl(List list) { - if (parent != null) { - parent.toListImpl(list); - } - list.add(this); - } - - public TruffleCallPath getParent() { - return parent; - } - - public OptimizedCallNode getCallNode() { - return callNode; - } - - public int getDepth() { - return parent == null ? 0 : (parent.getDepth() + 1); - } - - public int compareTo(TruffleCallPath o) { - return Objects.compare(this, o, new PathComparator()); - } - - private static class PathComparator implements Comparator { - public int compare(TruffleCallPath c1, TruffleCallPath c2) { - if (c1 == c2) { - return 0; - } - - Iterator p1 = c1.toList().iterator(); - Iterator p2 = c2.toList().iterator(); - - int cmp = 0; - while (cmp == 0 && (p1.hasNext() || p2.hasNext())) { - TruffleCallPath o1; - TruffleCallPath o2; - if (p1.hasNext()) { - o1 = p1.next(); - } else { - return -1; - } - if (p2.hasNext()) { - o2 = p2.next(); - } else { - return 1; - } - - if (o1 == o2) { - continue; - } - - SourceSection s1; - if (o1.callNode != null) { - s1 = o1.callNode.getEncapsulatingSourceSection(); - } else { - s1 = o1.getCallTarget().getRootNode().getSourceSection(); - } - - SourceSection s2; - if (o2.callNode != null) { - s2 = o2.callNode.getEncapsulatingSourceSection(); - } else { - s2 = o2.getCallTarget().getRootNode().getSourceSection(); - } - cmp = compareSourceSection(s2, s1); - - if (cmp == 0) { - cmp = o1.getCallTarget().toString().compareTo(o2.getCallTarget().toString()); - } - } - return cmp; - } - } - - private static int compareSourceSection(SourceSection s1, SourceSection s2) { - return Objects.compare(s1, s2, new Comparator() { - public int compare(SourceSection o1, SourceSection o2) { - if (o1 == o2) { - return 0; - } - if (o1 == null || o2 == null) { - return 0; - } - int cmp = 0; - if (o1.getSource() != null && o2.getSource() != null && !Objects.equals(o1.getSource().getName(), o2.getSource().getName())) { - cmp = o2.getSource().getName().compareTo(o1.getSource().getName()); - } - if (cmp == 0) { - cmp = o2.getStartLine() - o1.getStartLine(); - } - if (cmp == 0) { - cmp = o2.getStartColumn() - o1.getStartColumn(); - } - return cmp; - } - }); - } - - @Override - public int hashCode() { - final int prime = 31; - int result = 1; - result = prime * result + ((callNode == null) ? 0 : callNode.hashCode()); - result = prime * result + ((parent == null) ? 0 : parent.hashCode()); - result = prime * result + ((rootCallTarget == null) ? 0 : rootCallTarget.hashCode()); - return result; - } - - @Override - public boolean equals(Object obj) { - if (obj instanceof TruffleCallPath) { - TruffleCallPath other = (TruffleCallPath) obj; - if (other.callNode != callNode) { - return false; - } - if (!Objects.equals(other.parent, parent)) { - return false; - } - if (!Objects.equals(other.rootCallTarget, rootCallTarget)) { - return false; - } - return true; - } - return false; - } - - public TruffleCallPath append(TruffleCallPath path) { - if (getCallTarget() != path.getRootCallTarget()) { - throw new IllegalArgumentException("Pathes are not compatible and can therfore not be appended."); - } - - TruffleCallPath append = this; - for (TruffleCallPath childPath : path) { - if (!childPath.isRoot()) { - append = new TruffleCallPath(append, childPath.getCallNode()); - } - } - return append; - } - -} diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/TruffleCompiler.java --- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/TruffleCompiler.java Fri Apr 25 16:21:07 2014 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,36 +0,0 @@ -/* - * 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.truffle; - -import java.util.concurrent.*; - -import com.oracle.graal.api.code.*; - -/** - * Interface of the Truffle compiler producing an {@link InstalledCode} object from the partial - * evaluation starting with the AST represented by the given {@link OptimizedCallTarget} node. - */ -public interface TruffleCompiler { - - Future compile(OptimizedCallTarget node); -} diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/TruffleCompilerImpl.java --- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/TruffleCompilerImpl.java Fri Apr 25 16:21:07 2014 +0200 +++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/TruffleCompilerImpl.java Mon Apr 28 11:18:15 2014 +0200 @@ -27,14 +27,12 @@ import static com.oracle.graal.truffle.TruffleCompilerOptions.*; import java.util.*; -import java.util.concurrent.*; import com.oracle.graal.api.code.*; import com.oracle.graal.api.code.Assumptions.Assumption; import com.oracle.graal.api.code.CallingConvention.Type; import com.oracle.graal.api.meta.*; import com.oracle.graal.api.runtime.*; -import com.oracle.graal.compiler.*; import com.oracle.graal.compiler.target.*; import com.oracle.graal.debug.*; import com.oracle.graal.debug.Debug.Scope; @@ -55,7 +53,7 @@ /** * Implementation of the Truffle compiler using Graal. */ -public class TruffleCompilerImpl implements TruffleCompiler { +public class TruffleCompilerImpl { private final Providers providers; private final Suites suites; @@ -64,7 +62,6 @@ private final GraphBuilderConfiguration config; private final RuntimeProvider runtime; private final TruffleCache truffleCache; - private final ThreadPoolExecutor compileQueue; private static final Class[] SKIPPED_EXCEPTION_CLASSES = new Class[]{UnexpectedResultException.class, SlowPathException.class, ArithmeticException.class}; @@ -78,20 +75,6 @@ this.providers = backend.getProviders().copyWith(truffleReplacements); this.suites = backend.getSuites().getDefaultSuites(); - // Create compilation queue. - CompilerThreadFactory factory = new CompilerThreadFactory("TruffleCompilerThread", new CompilerThreadFactory.DebugConfigAccess() { - public GraalDebugConfig getDebugConfig() { - if (Debug.isEnabled()) { - GraalDebugConfig debugConfig = DebugEnvironment.initialize(TTY.out().out()); - debugConfig.dumpHandlers().add(new TruffleTreeDumpHandler()); - return debugConfig; - } else { - return null; - } - } - }); - compileQueue = new ThreadPoolExecutor(1, 1, 0L, TimeUnit.MILLISECONDS, new LinkedBlockingQueue(), factory); - ResolvedJavaType[] skippedExceptionTypes = getSkippedExceptionTypes(providers.getMetaAccess()); GraphBuilderConfiguration eagerConfig = GraphBuilderConfiguration.getEagerDefault(); eagerConfig.setSkippedExceptionTypes(skippedExceptionTypes); @@ -115,28 +98,15 @@ return skippedExceptionTypes; } - public Future compile(final OptimizedCallTarget compilable) { - return compileQueue.submit(new Callable() { - @Override - public InstalledCode call() throws Exception { - try (Scope s = Debug.scope("Truffle", new TruffleDebugJavaMethod(compilable))) { - return compileMethodImpl(compilable); - } catch (Throwable e) { - throw Debug.handle(e); - } - } - }); - } - public static final DebugTimer PartialEvaluationTime = Debug.timer("PartialEvaluationTime"); public static final DebugTimer CompilationTime = Debug.timer("CompilationTime"); public static final DebugTimer CodeInstallationTime = Debug.timer("CodeInstallation"); - private InstalledCode compileMethodImpl(final OptimizedCallTarget compilable) { + public void compileMethodImpl(final OptimizedCallTarget compilable) { final StructuredGraph graph; if (TraceTruffleCompilation.getValue()) { - OptimizedCallTarget.logOptimizingStart(compilable); + OptimizedCallTargetLog.logOptimizingStart(compilable); } long timeCompilationStarted = System.nanoTime(); @@ -146,49 +116,39 @@ } if (Thread.currentThread().isInterrupted()) { - return null; + return; } long timePartialEvaluationFinished = System.nanoTime(); int nodeCountPartialEval = graph.getNodeCount(); - InstalledCode compiledMethod = compileMethodHelper(graph, assumptions, compilable.toString(), compilable.getSpeculationLog()); + CompilationResult compilationResult = compileMethodHelper(graph, assumptions, compilable.toString(), compilable.getSpeculationLog(), compilable); long timeCompilationFinished = System.nanoTime(); int nodeCountLowered = graph.getNodeCount(); - if (compiledMethod == null) { - throw new BailoutException("Could not install method, code cache is full!"); - } - - if (!compiledMethod.isValid()) { - return null; - } - if (TraceTruffleCompilation.getValue()) { - byte[] code = compiledMethod.getCode(); - int calls = OptimizedCallUtils.countCalls(compilable.getInliningResult(), new TruffleCallPath(compilable)); - int inlinedCalls = (compilable.getInliningResult() != null ? compilable.getInliningResult().size() : 0); + int calls = OptimizedCallUtils.countCalls(compilable); + int inlinedCalls = OptimizedCallUtils.countCallsInlined(compilable); int dispatchedCalls = calls - inlinedCalls; Map properties = new LinkedHashMap<>(); - OptimizedCallTarget.addASTSizeProperty(compilable.getInliningResult(), new TruffleCallPath(compilable), properties); + OptimizedCallTargetLog.addASTSizeProperty(compilable, properties); properties.put("Time", String.format("%5.0f(%4.0f+%-4.0f)ms", // (timeCompilationFinished - timeCompilationStarted) / 1e6, // (timePartialEvaluationFinished - timeCompilationStarted) / 1e6, // (timeCompilationFinished - timePartialEvaluationFinished) / 1e6)); properties.put("CallNodes", String.format("I %5d/D %5d", inlinedCalls, dispatchedCalls)); properties.put("GraalNodes", String.format("%5d/%5d", nodeCountPartialEval, nodeCountLowered)); - properties.put("CodeSize", code != null ? code.length : 0); + properties.put("CodeSize", compilationResult.getTargetCodeSize()); properties.put("Source", formatSourceSection(compilable.getRootNode().getSourceSection())); - OptimizedCallTarget.logOptimizingDone(compilable, properties); + OptimizedCallTargetLog.logOptimizingDone(compilable, properties); } - return compiledMethod; } private static String formatSourceSection(SourceSection sourceSection) { return sourceSection != null ? sourceSection.toString() : "n/a"; } - public InstalledCode compileMethodHelper(StructuredGraph graph, Assumptions assumptions, String name, SpeculationLog speculationLog) { + public CompilationResult compileMethodHelper(StructuredGraph graph, Assumptions assumptions, String name, SpeculationLog speculationLog, InstalledCode predefinedInstalledCode) { try (Scope s = Debug.scope("TruffleFinal")) { Debug.dump(graph, "After TruffleTier"); } catch (Throwable e) { @@ -224,7 +184,7 @@ InstalledCode installedCode; try (Scope s = Debug.scope("CodeInstall", providers.getCodeCache()); TimerCloseable a = CodeInstallationTime.start()) { - installedCode = providers.getCodeCache().addMethod(graph.method(), result, speculationLog); + installedCode = providers.getCodeCache().addMethod(graph.method(), result, speculationLog, predefinedInstalledCode); } catch (Throwable e) { throw Debug.handle(e); } @@ -236,7 +196,7 @@ if (Debug.isLogEnabled()) { Debug.log(providers.getCodeCache().disassemble(result, installedCode)); } - return installedCode; + return result; } private PhaseSuite createGraphBuilderSuite() { diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/TruffleCompilerOptions.java --- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/TruffleCompilerOptions.java Fri Apr 25 16:21:07 2014 +0200 +++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/TruffleCompilerOptions.java Mon Apr 28 11:18:15 2014 +0200 @@ -54,7 +54,7 @@ @Option(help = "Enable automatic inlining of call targets") public static final OptionValue TruffleFunctionInlining = new OptionValue<>(true); @Option(help = "Maximum number of Graal IR nodes during partial evaluation") - public static final OptionValue TruffleGraphMaxNodes = new OptionValue<>(45000); + public static final OptionValue TruffleGraphMaxNodes = new OptionValue<>(200000); @Option(help = "Stop inlining if caller's cumulative tree size would exceed this limit") public static final OptionValue TruffleInliningMaxCallerSize = new OptionValue<>(2250); @Option(help = "Skip inlining candidate if its tree size exceeds this limit") @@ -72,15 +72,15 @@ @Option(help = "Enable asynchronous truffle compilation in background thread") public static final OptionValue TruffleBackgroundCompilation = new OptionValue<>(true); @Option(help = "") - public static final OptionValue TruffleUseTimeForCompilationDecision = new OptionValue<>(false); - @Option(help = "") public static final OptionValue TruffleCompilationDecisionTime = new OptionValue<>(100); @Option(help = "") public static final OptionValue TruffleCompilationDecisionTimePrintFail = new OptionValue<>(false); + @Option(help = "") + public static final OptionValue TruffleReturnTypeSpeculation = new OptionValue<>(true); // tracing @Option(help = "") - public static final OptionValue TraceTruffleCompilation = new OptionValue<>(true); + public static final OptionValue TraceTruffleCompilation = new OptionValue<>(false); @Option(help = "") public static final OptionValue TraceTruffleCompilationDetails = new OptionValue<>(false); @Option(help = "") @@ -94,9 +94,7 @@ @Option(help = "") public static final OptionValue TraceTruffleCacheDetails = new OptionValue<>(false); @Option(help = "") - public static final OptionValue TraceTruffleCompilationExceptions = new OptionValue<>(true); - @Option(help = "") - public static final OptionValue TruffleCompilationExceptionsAreFatal = new OptionValue<>(true); + public static final OptionValue TruffleCompilationExceptionsAreFatal = new OptionValue<>(false); @Option(help = "") public static final OptionValue TraceTruffleInlining = new OptionValue<>(false); @Option(help = "") diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/TruffleExpansionLogger.java --- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/TruffleExpansionLogger.java Fri Apr 25 16:21:07 2014 +0200 +++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/TruffleExpansionLogger.java Mon Apr 28 11:18:15 2014 +0200 @@ -23,7 +23,6 @@ package com.oracle.graal.truffle; import java.io.*; -import java.lang.reflect.*; import java.util.*; import java.util.Map.Entry; @@ -51,7 +50,7 @@ int sourceMethodBci = callTarget.invoke().bci(); ResolvedJavaMethod targetMethod = callTarget.targetMethod(); ResolvedJavaType targetReceiverType = null; - if (!Modifier.isStatic(sourceMethod.getModifiers()) && callTarget.receiver().isConstant()) { + if (!sourceMethod.isStatic() && callTarget.receiver().isConstant()) { targetReceiverType = providers.getMetaAccess().lookupJavaType(callTarget.arguments().first().asConstant()); } diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/TruffleInliningHandler.java --- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/TruffleInliningHandler.java Fri Apr 25 16:21:07 2014 +0200 +++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/TruffleInliningHandler.java Mon Apr 28 11:18:15 2014 +0200 @@ -24,164 +24,103 @@ import java.util.*; -import com.oracle.graal.truffle.OptimizedCallUtils.InlinedCallVisitor; import com.oracle.truffle.api.nodes.*; public final class TruffleInliningHandler { - private final ProfileScoreComparator inliningOrder = new ProfileScoreComparator(); - - private final OptimizedCallTarget callTarget; + private static final int MAXIMUM_RECURSIVE_DEPTH = 15; + private static final ProfileScoreComparator INLINING_SCORE = new ProfileScoreComparator(); private final TruffleInliningPolicy policy; - private final Map profiles; - private final Map inliningResultCache; + private final Map resultCache; - public TruffleInliningHandler(OptimizedCallTarget callTarget, TruffleInliningPolicy policy, Map inliningResultCache) { - this.callTarget = callTarget; + public TruffleInliningHandler(TruffleInliningPolicy policy) { this.policy = policy; - this.profiles = new HashMap<>(); - this.inliningResultCache = inliningResultCache; + this.resultCache = new HashMap<>(); } - public TruffleInliningResult inline(int originalTotalNodeCount) { - Set inlinedPathes = new HashSet<>(); - TruffleInliningResult result = new TruffleInliningResult(callTarget, inlinedPathes); - TruffleCallPath startPath = new TruffleCallPath(callTarget); - - PriorityQueue queue = new PriorityQueue<>(10, inliningOrder); - queueCallSitesForInlining(result, startPath, queue); - - int budget = TruffleCompilerOptions.TruffleInliningMaxCallerSize.getValue() - originalTotalNodeCount; - int index = 0; - while (!queue.isEmpty()) { - TruffleInliningProfile profile = queue.poll(); - profile.setQueryIndex(index); - budget = tryInline(queue, result, inlinedPathes, profile, budget); - profiles.put(profile.getCallPath(), profile); - index++; + public TruffleInliningResult decideInlining(OptimizedCallTarget target, int depth) { + if (resultCache.containsKey(target)) { + return resultCache.get(target); } + resultCache.put(target, null); + TruffleInliningResult result = decideInliningImpl(target, depth); + resultCache.put(target, result); return result; } - private int tryInline(PriorityQueue queue, TruffleInliningResult result, Set inlinedPathes, TruffleInliningProfile profile, int budget) { - - if (policy.isAllowed(result, profile, budget)) { - int remainingBudget; - inlinedPathes.add(profile.getCallPath()); - if (policy.isAllowedDeep(result, profile, budget)) { - if (profile.getRecursiveResult() != null) { - TruffleInliningResult inliningResult = profile.getRecursiveResult(); - for (TruffleCallPath recursiveInlinedPath : inliningResult) { - inlinedPathes.add(profile.getCallPath().append(recursiveInlinedPath)); - } - } - remainingBudget = budget - profile.getDeepNodeCount(); - } else { - remainingBudget = budget - profile.getNodeCount(); + private TruffleInliningResult decideInliningImpl(OptimizedCallTarget target, int depth) { + List profiles = lookupProfiles(target, depth); + Set inlined = new HashSet<>(); + Collections.sort(profiles, INLINING_SCORE); + int budget = TruffleCompilerOptions.TruffleInliningMaxCallerSize.getValue() - OptimizedCallUtils.countNonTrivialNodes(target, true); + int index = 0; + for (TruffleInliningProfile profile : profiles) { + profile.setQueryIndex(index++); + if (policy.isAllowed(profile, budget)) { + inlined.add(profile); + budget -= profile.getDeepNodeCount(); } - - queueCallSitesForInlining(result, profile.getCallPath(), queue); - return remainingBudget; } - return budget; + int deepNodeCount = TruffleCompilerOptions.TruffleInliningMaxCallerSize.getValue() - budget; + return new TruffleInliningResult(target, profiles, inlined, deepNodeCount); + } + + private List lookupProfiles(final OptimizedCallTarget target, int depth) { + final List callNodes = new ArrayList<>(); + target.getRootNode().accept(new NodeVisitor() { + public boolean visit(Node node) { + if (node instanceof OptimizedDirectCallNode) { + callNodes.add((OptimizedDirectCallNode) node); + } + return true; + } + }); + final List profiles = new ArrayList<>(); + for (OptimizedDirectCallNode callNode : callNodes) { + profiles.add(lookupProfile(target, callNode, depth)); + } + return profiles; + } + + public TruffleInliningProfile lookupProfile(OptimizedCallTarget parentTarget, OptimizedDirectCallNode ocn, int depth) { + OptimizedCallTarget target = ocn.getCurrentCallTarget(); + + int callSites = ocn.getCurrentCallTarget().getKnownCallSiteCount(); + int nodeCount = OptimizedCallUtils.countNonTrivialNodes(target, false); + double frequency = calculateFrequency(parentTarget, ocn); + boolean forced = ocn.isInliningForced(); + + int deepNodeCount; + TruffleInliningResult recursiveResult; + boolean recursiveCall = false; + if (target.inliningPerformed || depth > MAXIMUM_RECURSIVE_DEPTH) { + deepNodeCount = OptimizedCallUtils.countNonTrivialNodes(target, true); + recursiveResult = null; + } else { + recursiveResult = decideInlining(ocn.getCurrentCallTarget(), depth + 1); + if (recursiveResult == null) { + recursiveCall = true; + deepNodeCount = Integer.MAX_VALUE; + } else { + deepNodeCount = recursiveResult.getNodeCount(); + } + } + + TruffleInliningProfile profile = new TruffleInliningProfile(ocn, callSites, nodeCount, deepNodeCount, frequency, forced, recursiveCall, recursiveResult); + profile.setScore(policy.calculateScore(profile)); + return profile; } public TruffleInliningPolicy getPolicy() { return policy; } - public Map getProfiles() { - return profiles; - } - - private void queueCallSitesForInlining(final TruffleInliningResult currentDecision, TruffleCallPath fromPath, final Collection queue) { - fromPath.getCallTarget().getRootNode().accept(new InlinedCallVisitor(currentDecision, fromPath) { - @Override - public boolean visit(TruffleCallPath path, Node node) { - if (node instanceof OptimizedCallNode) { - if (!currentDecision.isInlined(path)) { - addToQueue(queue, currentDecision, path); - } - } - return true; - } - }); - } - - private void addToQueue(final Collection queue, final TruffleInliningResult currentDecision, TruffleCallPath path) { - queue.add(lookupProfile(currentDecision, path)); - } - - public List lookupProfiles(final TruffleInliningResult currentDecision, TruffleCallPath fromPath) { - final List pathes = new ArrayList<>(); - fromPath.getCallTarget().getRootNode().accept(new InlinedCallVisitor(currentDecision, fromPath) { - @Override - public boolean visit(TruffleCallPath path, Node node) { - if (node instanceof OptimizedCallNode) { - pathes.add(lookupProfile(currentDecision, path)); - } - return true; - } - }); - return pathes; + private static double calculateFrequency(OptimizedCallTarget target, OptimizedDirectCallNode ocn) { + return (double) Math.max(1, ocn.getCallCount()) / (double) Math.max(1, target.getCompilationProfile().getCallCount()); } - public TruffleInliningProfile lookupProfile(TruffleInliningResult state, TruffleCallPath callPath) { - TruffleInliningProfile profile = profiles.get(callPath); - if (profile != null) { - return profile; - } - - int callSites = callPath.getCallTarget().getKnownCallSiteCount(); - int nodeCount = OptimizedCallUtils.countNonTrivialNodes(state, callPath); - double frequency = calculatePathFrequency(callPath); - boolean forced = callPath.getCallNode().isInlined(); - TruffleInliningResult recursiveResult = lookupChildResult(callPath, nodeCount); - int deepNodeCount = OptimizedCallUtils.countNonTrivialNodes(recursiveResult, new TruffleCallPath(callPath.getCallTarget())); - - profile = new TruffleInliningProfile(callPath, callSites, nodeCount, deepNodeCount, frequency, forced, recursiveResult); - profile.setScore(policy.calculateScore(profile)); - profiles.put(callPath, profile); - - return profile; - } - - private TruffleInliningResult lookupChildResult(TruffleCallPath callPath, int nodeCount) { - OptimizedCallTarget target = callPath.getCallTarget(); - - TruffleInliningResult recursiveResult = target.getInliningResult(); - - if (recursiveResult == null) { - recursiveResult = inliningResultCache.get(callPath.getCallTarget()); - - if (recursiveResult == null) { - if (inliningResultCache.containsKey(target)) { - // cancel on recursion - return new TruffleInliningResult(target, new HashSet()); - } - inliningResultCache.put(target, null); - TruffleInliningHandler handler = new TruffleInliningHandler(target, policy, inliningResultCache); - recursiveResult = handler.inline(nodeCount); - inliningResultCache.put(callPath.getCallTarget(), recursiveResult); - } - } - return recursiveResult; - } - - private static double calculatePathFrequency(TruffleCallPath callPath) { - int parentCallCount = -1; - double f = 1.0d; - for (TruffleCallPath path : callPath.toList()) { - if (parentCallCount != -1) { - f *= path.getCallNode().getCallCount() / (double) parentCallCount; - } - parentCallCount = path.getCallTarget().getCompilationProfile().getCallCount(); - } - return f; - } - - private final class ProfileScoreComparator implements Comparator { + private final static class ProfileScoreComparator implements Comparator { public int compare(TruffleInliningProfile o1, TruffleInliningProfile o2) { return Double.compare(o2.getScore(), o1.getScore()); diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/TruffleInliningPolicy.java --- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/TruffleInliningPolicy.java Fri Apr 25 16:21:07 2014 +0200 +++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/TruffleInliningPolicy.java Mon Apr 28 11:18:15 2014 +0200 @@ -24,9 +24,7 @@ public interface TruffleInliningPolicy { - boolean isAllowed(TruffleInliningResult state, TruffleInliningProfile profile, int nodeCountBudget); - - boolean isAllowedDeep(TruffleInliningResult state, TruffleInliningProfile profile, int nodeCountBudget); + boolean isAllowed(TruffleInliningProfile profile, int currentBudgetLeft); double calculateScore(TruffleInliningProfile profile); diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/TruffleInliningProfile.java --- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/TruffleInliningProfile.java Fri Apr 25 16:21:07 2014 +0200 +++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/TruffleInliningProfile.java Mon Apr 28 11:18:15 2014 +0200 @@ -24,34 +24,41 @@ import java.util.*; -public class TruffleInliningProfile implements Comparable { +public class TruffleInliningProfile { - private final TruffleCallPath callPath; - + private final OptimizedDirectCallNode callNode; private final int nodeCount; private final int deepNodeCount; private final int callSites; private final double frequency; private final boolean forced; + private final boolean recursiveCall; private final TruffleInliningResult recursiveResult; private String failedReason; private int queryIndex = -1; private double score; - public TruffleInliningProfile(TruffleCallPath callPath, int callSites, int nodeCount, int deepNodeCount, double frequency, boolean forced, TruffleInliningResult recursiveResult) { - if (callPath.isRoot()) { - throw new IllegalArgumentException("Root call path not profilable."); - } + public TruffleInliningProfile(OptimizedDirectCallNode callNode, int callSites, int nodeCount, int deepNodeCount, double frequency, boolean forced, boolean recursiveCall, + TruffleInliningResult recursiveResult) { + this.callNode = callNode; this.callSites = callSites; - this.callPath = callPath; this.nodeCount = nodeCount; this.deepNodeCount = deepNodeCount; this.frequency = frequency; + this.recursiveCall = recursiveCall; this.forced = forced; this.recursiveResult = recursiveResult; } + public boolean isRecursiveCall() { + return recursiveCall; + } + + public OptimizedDirectCallNode getCallNode() { + return callNode; + } + public int getCallSites() { return callSites; } @@ -100,21 +107,12 @@ return deepNodeCount; } - public TruffleCallPath getCallPath() { - return callPath; - } - - public int compareTo(TruffleInliningProfile o) { - return callPath.compareTo(o.callPath); - } - public Map getDebugProperties() { Map properties = new LinkedHashMap<>(); - properties.put("callSites", callSites); - properties.put("nodeCount", nodeCount); + properties.put("nodeCount", String.format("%5d/%5d", deepNodeCount, nodeCount)); properties.put("frequency", frequency); - properties.put("score", score); - properties.put(String.format("index=%3d, force=%s", queryIndex, (forced ? "Y" : "N")), ""); + properties.put("score", String.format("%8.4f", getScore())); + properties.put(String.format("index=%3d, force=%s, callSites=%2d", queryIndex, (forced ? "Y" : "N"), callSites), ""); properties.put("reason", failedReason); return properties; } diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/TruffleInliningResult.java --- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/TruffleInliningResult.java Fri Apr 25 16:21:07 2014 +0200 +++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/TruffleInliningResult.java Mon Apr 28 11:18:15 2014 +0200 @@ -24,34 +24,49 @@ import java.util.*; -public final class TruffleInliningResult implements Iterable { +public final class TruffleInliningResult implements Iterable { private final OptimizedCallTarget callTarget; - private final Set inlinedPathes; + private final Map profiles; + private final Set inlined; + private final int nodeCount; - public TruffleInliningResult(OptimizedCallTarget callTarget, Set pathes) { + public TruffleInliningResult(OptimizedCallTarget callTarget, List profiles, Set inlined, int nodeCount) { this.callTarget = callTarget; - this.inlinedPathes = pathes; + this.profiles = new HashMap<>(); + for (TruffleInliningProfile profile : profiles) { + this.profiles.put(profile.getCallNode(), profile); + } + this.nodeCount = nodeCount; + this.inlined = inlined; + } + + public Map getProfiles() { + return profiles; + } + + public int getNodeCount() { + return nodeCount; } public OptimizedCallTarget getCallTarget() { return callTarget; } - public boolean isInlined(TruffleCallPath path) { - return inlinedPathes.contains(path); + public boolean isInlined(OptimizedDirectCallNode path) { + return inlined.contains(profiles.get(path)); } public int size() { - return inlinedPathes.size(); + return inlined.size(); } - public Iterator iterator() { - return Collections.unmodifiableSet(inlinedPathes).iterator(); + public Iterator iterator() { + return Collections.unmodifiableSet(inlined).iterator(); } @Override public String toString() { - return inlinedPathes.toString(); + return inlined.toString(); } } diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/TruffleReplacements.java --- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/TruffleReplacements.java Fri Apr 25 16:21:07 2014 +0200 +++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/TruffleReplacements.java Mon Apr 28 11:18:15 2014 +0200 @@ -26,7 +26,7 @@ import com.oracle.graal.api.meta.*; import com.oracle.graal.api.replacements.*; -import com.oracle.graal.graph.*; +import com.oracle.graal.compiler.common.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.spi.*; import com.oracle.graal.phases.util.*; diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/TruffleTreeDumpHandler.java --- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/TruffleTreeDumpHandler.java Fri Apr 25 16:21:07 2014 +0200 +++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/TruffleTreeDumpHandler.java Mon Apr 28 11:18:15 2014 +0200 @@ -22,8 +22,6 @@ */ package com.oracle.graal.truffle; -import java.util.*; - import com.oracle.graal.debug.*; import com.oracle.truffle.api.*; import com.oracle.truffle.api.nodes.*; @@ -46,7 +44,6 @@ final OptimizedCallTarget oct = (OptimizedCallTarget) callTarget; visitor.beginGroup(callTarget.toString()); - dumpInlinedCalls(visitor, oct); dumpFullTree(visitor, message, oct); visitor.printToNetwork(false); } @@ -54,22 +51,17 @@ private static void dumpFullTree(final GraphPrintVisitor visitor, final String message, final OptimizedCallTarget oct) { visitor.setChildSupplier(new ChildSupplier() { - private TruffleCallPath currentPath = new TruffleCallPath(oct); public Object startNode(Object callNode) { - if (callNode instanceof OptimizedCallNode) { - currentPath = new TruffleCallPath(currentPath, (OptimizedCallNode) callNode); - if (oct.getInliningResult() != null && oct.getInliningResult().isInlined(currentPath)) { - return ((OptimizedCallNode) callNode).getCurrentRootNode(); + if (callNode instanceof OptimizedDirectCallNode) { + if (((OptimizedDirectCallNode) callNode).isInlined()) { + return ((OptimizedDirectCallNode) callNode).getCurrentRootNode(); } } return null; } public void endNode(Object callNode) { - if (callNode instanceof OptimizedCallNode) { - currentPath = currentPath.getParent(); - } } }); @@ -77,23 +69,6 @@ visitor.setChildSupplier(null); } - private static void dumpInlinedCalls(final GraphPrintVisitor visitor, final OptimizedCallTarget oct) { - final Set visitedRoots = new HashSet<>(); - oct.getRootNode().accept(new OptimizedCallUtils.InlinedCallVisitor(oct.getInliningResult(), new TruffleCallPath(oct)) { - @Override - public boolean visit(TruffleCallPath path, Node node) { - if (node instanceof OptimizedCallNode) { - OptimizedCallTarget target = ((OptimizedCallNode) node).getCurrentCallTarget(); - if (!visitedRoots.contains(target)) { - visitor.beginGraph("inlined " + target.toString()).visit(target.getRootNode()); - visitedRoots.add(target); - } - } - return true; - } - }); - } - public void close() { // nothing to do } diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/LoadIndexedFinalNode.java --- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/LoadIndexedFinalNode.java Fri Apr 25 16:21:07 2014 +0200 +++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/LoadIndexedFinalNode.java Mon Apr 28 11:18:15 2014 +0200 @@ -23,6 +23,7 @@ package com.oracle.graal.truffle.nodes; import com.oracle.graal.api.meta.*; +import com.oracle.graal.compiler.common.type.*; import com.oracle.graal.graph.*; import com.oracle.graal.graph.spi.*; import com.oracle.graal.nodes.*; @@ -58,7 +59,7 @@ } private static Stamp createStamp(ValueNode array, Kind kind) { - ResolvedJavaType type = ObjectStamp.typeOrNull(array); + ResolvedJavaType type = StampTool.typeOrNull(array); if (kind == Kind.Object && type != null) { return StampFactory.declared(type.getComponentType()); } else { diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/arithmetic/IntegerAddExactNode.java --- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/arithmetic/IntegerAddExactNode.java Fri Apr 25 16:21:07 2014 +0200 +++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/arithmetic/IntegerAddExactNode.java Mon Apr 28 11:18:15 2014 +0200 @@ -23,6 +23,7 @@ package com.oracle.graal.truffle.nodes.arithmetic; import com.oracle.graal.api.meta.*; +import com.oracle.graal.compiler.common.type.*; import com.oracle.graal.graph.*; import com.oracle.graal.graph.spi.*; import com.oracle.graal.nodes.*; @@ -77,7 +78,7 @@ } @Override - public IntegerExactArithmeticSplitNode createSplit(AbstractBeginNode next, AbstractBeginNode deopt) { + public IntegerExactArithmeticSplitNode createSplit(BeginNode next, BeginNode deopt) { return graph().add(new IntegerAddExactSplitNode(stamp(), x(), y(), next, deopt)); } diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/arithmetic/IntegerAddExactSplitNode.java --- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/arithmetic/IntegerAddExactSplitNode.java Fri Apr 25 16:21:07 2014 +0200 +++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/arithmetic/IntegerAddExactSplitNode.java Mon Apr 28 11:18:15 2014 +0200 @@ -23,13 +23,13 @@ package com.oracle.graal.truffle.nodes.arithmetic; import com.oracle.graal.api.meta.*; +import com.oracle.graal.compiler.common.type.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.spi.*; -import com.oracle.graal.nodes.type.*; public class IntegerAddExactSplitNode extends IntegerExactArithmeticSplitNode { - public IntegerAddExactSplitNode(Stamp stamp, ValueNode x, ValueNode y, AbstractBeginNode next, AbstractBeginNode overflowSuccessor) { + public IntegerAddExactSplitNode(Stamp stamp, ValueNode x, ValueNode y, BeginNode next, BeginNode overflowSuccessor) { super(stamp, x, y, next, overflowSuccessor); } diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/arithmetic/IntegerExactArithmeticNode.java --- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/arithmetic/IntegerExactArithmeticNode.java Fri Apr 25 16:21:07 2014 +0200 +++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/arithmetic/IntegerExactArithmeticNode.java Mon Apr 28 11:18:15 2014 +0200 @@ -28,5 +28,5 @@ interface IntegerExactArithmeticNode extends Lowerable, IterableNodeType { - IntegerExactArithmeticSplitNode createSplit(AbstractBeginNode next, AbstractBeginNode deopt); + IntegerExactArithmeticSplitNode createSplit(BeginNode next, BeginNode deopt); } diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/arithmetic/IntegerExactArithmeticSplitNode.java --- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/arithmetic/IntegerExactArithmeticSplitNode.java Fri Apr 25 16:21:07 2014 +0200 +++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/arithmetic/IntegerExactArithmeticSplitNode.java Mon Apr 28 11:18:15 2014 +0200 @@ -23,19 +23,19 @@ package com.oracle.graal.truffle.nodes.arithmetic; import com.oracle.graal.api.meta.*; +import com.oracle.graal.compiler.common.type.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.calc.*; import com.oracle.graal.nodes.spi.*; -import com.oracle.graal.nodes.type.*; public abstract class IntegerExactArithmeticSplitNode extends ControlSplitNode implements LIRLowerable { - @Successor private AbstractBeginNode overflowSuccessor; - @Successor private AbstractBeginNode next; + @Successor private BeginNode overflowSuccessor; + @Successor private BeginNode next; @Input private ValueNode x; @Input private ValueNode y; - public IntegerExactArithmeticSplitNode(Stamp stamp, ValueNode x, ValueNode y, AbstractBeginNode next, AbstractBeginNode overflowSuccessor) { + public IntegerExactArithmeticSplitNode(Stamp stamp, ValueNode x, ValueNode y, BeginNode next, BeginNode overflowSuccessor) { super(stamp); this.x = x; this.y = y; @@ -44,20 +44,20 @@ } @Override - public double probability(AbstractBeginNode successor) { + public double probability(BeginNode successor) { return successor == next ? 1 : 0; } @Override - public void setProbability(AbstractBeginNode successor, double value) { + public void setProbability(BeginNode successor, double value) { assert probability(successor) == value; } - public AbstractBeginNode getNext() { + public BeginNode getNext() { return next; } - public AbstractBeginNode getOverflowSuccessor() { + public BeginNode getOverflowSuccessor() { return overflowSuccessor; } diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/arithmetic/IntegerMulExactNode.java --- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/arithmetic/IntegerMulExactNode.java Fri Apr 25 16:21:07 2014 +0200 +++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/arithmetic/IntegerMulExactNode.java Mon Apr 28 11:18:15 2014 +0200 @@ -23,12 +23,12 @@ package com.oracle.graal.truffle.nodes.arithmetic; import com.oracle.graal.api.meta.*; +import com.oracle.graal.compiler.common.type.*; import com.oracle.graal.graph.*; import com.oracle.graal.graph.spi.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.calc.*; import com.oracle.graal.nodes.spi.*; -import com.oracle.graal.nodes.type.*; import com.oracle.truffle.api.*; /** @@ -74,7 +74,7 @@ } @Override - public IntegerExactArithmeticSplitNode createSplit(AbstractBeginNode next, AbstractBeginNode deopt) { + public IntegerExactArithmeticSplitNode createSplit(BeginNode next, BeginNode deopt) { return graph().add(new IntegerMulExactSplitNode(stamp(), x(), y(), next, deopt)); } diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/arithmetic/IntegerMulExactSplitNode.java --- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/arithmetic/IntegerMulExactSplitNode.java Fri Apr 25 16:21:07 2014 +0200 +++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/arithmetic/IntegerMulExactSplitNode.java Mon Apr 28 11:18:15 2014 +0200 @@ -23,13 +23,13 @@ package com.oracle.graal.truffle.nodes.arithmetic; import com.oracle.graal.api.meta.*; +import com.oracle.graal.compiler.common.type.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.spi.*; -import com.oracle.graal.nodes.type.*; public class IntegerMulExactSplitNode extends IntegerExactArithmeticSplitNode { - public IntegerMulExactSplitNode(Stamp stamp, ValueNode x, ValueNode y, AbstractBeginNode next, AbstractBeginNode overflowSuccessor) { + public IntegerMulExactSplitNode(Stamp stamp, ValueNode x, ValueNode y, BeginNode next, BeginNode overflowSuccessor) { super(stamp, x, y, next, overflowSuccessor); } diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/arithmetic/IntegerSubExactNode.java --- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/arithmetic/IntegerSubExactNode.java Fri Apr 25 16:21:07 2014 +0200 +++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/arithmetic/IntegerSubExactNode.java Mon Apr 28 11:18:15 2014 +0200 @@ -23,6 +23,7 @@ package com.oracle.graal.truffle.nodes.arithmetic; import com.oracle.graal.api.meta.*; +import com.oracle.graal.compiler.common.type.*; import com.oracle.graal.graph.*; import com.oracle.graal.graph.spi.*; import com.oracle.graal.nodes.*; @@ -77,7 +78,7 @@ } @Override - public IntegerExactArithmeticSplitNode createSplit(AbstractBeginNode next, AbstractBeginNode deopt) { + public IntegerExactArithmeticSplitNode createSplit(BeginNode next, BeginNode deopt) { return graph().add(new IntegerSubExactSplitNode(stamp(), x(), y(), next, deopt)); } diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/arithmetic/IntegerSubExactSplitNode.java --- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/arithmetic/IntegerSubExactSplitNode.java Fri Apr 25 16:21:07 2014 +0200 +++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/arithmetic/IntegerSubExactSplitNode.java Mon Apr 28 11:18:15 2014 +0200 @@ -23,13 +23,13 @@ package com.oracle.graal.truffle.nodes.arithmetic; import com.oracle.graal.api.meta.*; +import com.oracle.graal.compiler.common.type.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.spi.*; -import com.oracle.graal.nodes.type.*; public class IntegerSubExactSplitNode extends IntegerExactArithmeticSplitNode { - public IntegerSubExactSplitNode(Stamp stamp, ValueNode x, ValueNode y, AbstractBeginNode next, AbstractBeginNode overflowSuccessor) { + public IntegerSubExactSplitNode(Stamp stamp, ValueNode x, ValueNode y, BeginNode next, BeginNode overflowSuccessor) { super(stamp, x, y, next, overflowSuccessor); } diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/frame/ForceMaterializeNode.java --- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/frame/ForceMaterializeNode.java Fri Apr 25 16:21:07 2014 +0200 +++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/frame/ForceMaterializeNode.java Mon Apr 28 11:18:15 2014 +0200 @@ -22,12 +22,11 @@ */ package com.oracle.graal.truffle.nodes.frame; -import com.oracle.graal.compiler.gen.*; -import com.oracle.graal.compiler.target.*; +import com.oracle.graal.compiler.common.type.*; import com.oracle.graal.nodes.*; -import com.oracle.graal.nodes.type.*; +import com.oracle.graal.nodes.spi.*; -public class ForceMaterializeNode extends FixedWithNextNode implements LIRGenLowerable { +public class ForceMaterializeNode extends FixedWithNextNode implements LIRLowerable { @Input private ValueNode object; @@ -36,7 +35,7 @@ this.object = object; } - public void generate(NodeLIRBuilder generator) { + public void generate(NodeLIRBuilderTool generator) { // nothing to do } diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/frame/NewFrameNode.java --- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/frame/NewFrameNode.java Fri Apr 25 16:21:07 2014 +0200 +++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/frame/NewFrameNode.java Mon Apr 28 11:18:15 2014 +0200 @@ -27,12 +27,13 @@ import com.oracle.graal.api.meta.*; import com.oracle.graal.api.replacements.*; import com.oracle.graal.api.runtime.*; +import com.oracle.graal.compiler.common.*; +import com.oracle.graal.compiler.common.type.*; import com.oracle.graal.graph.*; import com.oracle.graal.graph.spi.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.java.*; import com.oracle.graal.nodes.spi.*; -import com.oracle.graal.nodes.type.*; import com.oracle.graal.nodes.util.*; import com.oracle.graal.nodes.virtual.*; import com.oracle.graal.truffle.*; diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/typesystem/CustomizedUnsafeLoadFinalNode.java --- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/typesystem/CustomizedUnsafeLoadFinalNode.java Fri Apr 25 16:21:07 2014 +0200 +++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/typesystem/CustomizedUnsafeLoadFinalNode.java Mon Apr 28 11:18:15 2014 +0200 @@ -23,13 +23,14 @@ package com.oracle.graal.truffle.nodes.typesystem; import com.oracle.graal.api.meta.*; +import com.oracle.graal.compiler.common.calc.*; +import com.oracle.graal.compiler.common.type.*; import com.oracle.graal.graph.*; import com.oracle.graal.graph.spi.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.calc.*; import com.oracle.graal.nodes.extended.*; import com.oracle.graal.nodes.spi.*; -import com.oracle.graal.nodes.type.*; import com.oracle.graal.truffle.nodes.*; import com.oracle.truffle.api.*; @@ -88,7 +89,7 @@ public void lower(LoweringTool tool) { CompareNode compare = CompareNode.createCompareNode(graph(), Condition.EQ, condition, ConstantNode.forBoolean(true, graph())); LocationIdentity locationIdentity; - if (location.asConstant().isNull()) { + if (!location.isConstant() || location.asConstant().isNull()) { locationIdentity = LocationIdentity.ANY_LOCATION; } else { locationIdentity = ObjectLocationIdentity.create(location.asConstant()); diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/typesystem/CustomizedUnsafeLoadMacroNode.java --- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/typesystem/CustomizedUnsafeLoadMacroNode.java Fri Apr 25 16:21:07 2014 +0200 +++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/typesystem/CustomizedUnsafeLoadMacroNode.java Mon Apr 28 11:18:15 2014 +0200 @@ -23,6 +23,7 @@ package com.oracle.graal.truffle.nodes.typesystem; import com.oracle.graal.api.meta.*; +import com.oracle.graal.compiler.common.calc.*; import com.oracle.graal.graph.*; import com.oracle.graal.graph.spi.*; import com.oracle.graal.nodes.*; diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/typesystem/UnsafeTypeCastMacroNode.java --- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/typesystem/UnsafeTypeCastMacroNode.java Fri Apr 25 16:21:07 2014 +0200 +++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/typesystem/UnsafeTypeCastMacroNode.java Mon Apr 28 11:18:15 2014 +0200 @@ -23,12 +23,13 @@ package com.oracle.graal.truffle.nodes.typesystem; import com.oracle.graal.api.meta.*; +import com.oracle.graal.compiler.common.calc.*; +import com.oracle.graal.compiler.common.type.*; import com.oracle.graal.graph.*; import com.oracle.graal.graph.spi.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.calc.*; import com.oracle.graal.nodes.extended.*; -import com.oracle.graal.nodes.type.*; import com.oracle.graal.truffle.nodes.asserts.*; import com.oracle.truffle.api.*; diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/substitutions/CompilerDirectivesSubstitutions.java --- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/substitutions/CompilerDirectivesSubstitutions.java Fri Apr 25 16:21:07 2014 +0200 +++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/substitutions/CompilerDirectivesSubstitutions.java Mon Apr 28 11:18:15 2014 +0200 @@ -55,6 +55,11 @@ } @MethodSubstitution + public static boolean inCompiledCode() { + return true; + } + + @MethodSubstitution public static void interpreterOnly(@SuppressWarnings("unused") Runnable runnable) { } diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/substitutions/OptimizedCallTargetSubstitutions.java --- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/substitutions/OptimizedCallTargetSubstitutions.java Fri Apr 25 16:21:07 2014 +0200 +++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/substitutions/OptimizedCallTargetSubstitutions.java Mon Apr 28 11:18:15 2014 +0200 @@ -23,6 +23,8 @@ package com.oracle.graal.truffle.substitutions; import com.oracle.graal.api.replacements.*; +import com.oracle.graal.compiler.common.type.*; +import com.oracle.graal.nodes.*; import com.oracle.graal.truffle.*; import com.oracle.graal.truffle.nodes.frame.*; import com.oracle.truffle.api.frame.*; @@ -34,4 +36,9 @@ private static FrameWithoutBoxing createFrame(FrameDescriptor descriptor, Object[] args) { return NewFrameNode.allocate(FrameWithoutBoxing.class, descriptor, args); } + + @MethodSubstitution + private static Object castArrayFixedLength(Object[] args, int length) { + return PiArrayNode.piArrayCast(args, length, StampFactory.forNodeIntrinsic()); + } } diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/EarlyReadEliminationPhase.java --- a/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/EarlyReadEliminationPhase.java Fri Apr 25 16:21:07 2014 +0200 +++ b/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/EarlyReadEliminationPhase.java Mon Apr 28 11:18:15 2014 +0200 @@ -22,7 +22,7 @@ */ package com.oracle.graal.virtual.phases.ea; -import static com.oracle.graal.phases.GraalOptions.*; +import static com.oracle.graal.compiler.common.GraalOptions.*; import com.oracle.graal.nodes.*; import com.oracle.graal.phases.common.*; diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/EffectsClosure.java --- a/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/EffectsClosure.java Fri Apr 25 16:21:07 2014 +0200 +++ b/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/EffectsClosure.java Mon Apr 28 11:18:15 2014 +0200 @@ -22,10 +22,12 @@ */ package com.oracle.graal.virtual.phases.ea; -import static com.oracle.graal.phases.GraalOptions.*; +import static com.oracle.graal.compiler.common.GraalOptions.*; import java.util.*; +import com.oracle.graal.compiler.common.*; +import com.oracle.graal.compiler.common.cfg.*; import com.oracle.graal.debug.*; import com.oracle.graal.graph.*; import com.oracle.graal.nodes.*; @@ -43,7 +45,7 @@ protected final NodeMap aliases; protected final BlockMap blockEffects; - private final IdentityHashMap loopMergeEffects = new IdentityHashMap<>(); + private final IdentityHashMap, GraphEffectList> loopMergeEffects = new IdentityHashMap<>(); private final IdentityHashMap loopEntryStates = new IdentityHashMap<>(); private boolean changed; @@ -105,7 +107,7 @@ } @Override - protected List processLoop(Loop loop, Void initialState) { + protected List processLoop(Loop loop, Void initialState) { LoopInfo info = ReentrantBlockIterator.processLoop(this, loop, initialState); apply(loopMergeEffects.get(loop), loop); return info.exitStates; @@ -150,7 +152,7 @@ } @Override - protected final List processLoop(Loop loop, BlockT initialState) { + protected final List processLoop(Loop loop, BlockT initialState) { BlockT loopEntryState = initialState; BlockT lastMergedState = cloneState(initialState); MergeProcessor mergeProcessor = createMergeProcessor(loop.header); @@ -174,7 +176,7 @@ loopMergeEffects.put(loop, mergeProcessor.afterMergeEffects); assert info.exitStates.size() == loop.exits.size(); - loopEntryStates.put(loop.loopBegin(), loopEntryState); + loopEntryStates.put((LoopBeginNode) loop.header.getBeginNode(), loopEntryState); for (int i = 0; i < loop.exits.size(); i++) { assert info.exitStates.get(i) != null : "no loop exit state at " + loop.exits.get(i) + " / " + loop.header; } diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/EffectsPhase.java --- a/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/EffectsPhase.java Fri Apr 25 16:21:07 2014 +0200 +++ b/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/EffectsPhase.java Mon Apr 28 11:18:15 2014 +0200 @@ -90,7 +90,9 @@ listener.getChangedNodes().add(node); } } - canonicalizer.applyIncremental(graph, context, listener.getChangedNodes()); + if (canonicalizer != null) { + canonicalizer.applyIncremental(graph, context, listener.getChangedNodes()); + } } changed = true; } diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/IterativeInliningPhase.java --- a/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/IterativeInliningPhase.java Fri Apr 25 16:21:07 2014 +0200 +++ b/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/IterativeInliningPhase.java Mon Apr 28 11:18:15 2014 +0200 @@ -22,8 +22,8 @@ */ package com.oracle.graal.virtual.phases.ea; +import static com.oracle.graal.compiler.common.GraalOptions.*; import static com.oracle.graal.debug.Debug.*; -import static com.oracle.graal.phases.GraalOptions.*; import java.util.*; diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/PEReadEliminationBlockState.java --- a/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/PEReadEliminationBlockState.java Fri Apr 25 16:21:07 2014 +0200 +++ b/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/PEReadEliminationBlockState.java Mon Apr 28 11:18:15 2014 +0200 @@ -34,10 +34,10 @@ static class ReadCacheEntry { - public final ResolvedJavaField identity; + public final LocationIdentity identity; public final ValueNode object; - public ReadCacheEntry(ResolvedJavaField identity, ValueNode object) { + public ReadCacheEntry(LocationIdentity identity, ValueNode object) { this.identity = identity; this.object = object; } @@ -95,7 +95,7 @@ return super.equivalentTo(other); } - public void addReadCache(ValueNode object, ResolvedJavaField identity, ValueNode value, PartialEscapeClosure closure) { + public void addReadCache(ValueNode object, LocationIdentity identity, ValueNode value, PartialEscapeClosure closure) { ValueNode cacheObject; ObjectState obj = closure.getObjectState(this, object); if (obj != null) { @@ -107,7 +107,7 @@ readCache.put(new ReadCacheEntry(identity, cacheObject), value); } - public ValueNode getReadCache(ValueNode object, ResolvedJavaField identity, PartialEscapeClosure closure) { + public ValueNode getReadCache(ValueNode object, LocationIdentity identity, PartialEscapeClosure closure) { ValueNode cacheObject; ObjectState obj = closure.getObjectState(this, object); if (obj != null) { diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/PEReadEliminationClosure.java --- a/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/PEReadEliminationClosure.java Fri Apr 25 16:21:07 2014 +0200 +++ b/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/PEReadEliminationClosure.java Mon Apr 28 11:18:15 2014 +0200 @@ -83,6 +83,17 @@ } else { processIdentity(state, ANY_LOCATION); } + } else if (node instanceof ArrayLengthNode) { + ArrayLengthNode length = (ArrayLengthNode) node; + ValueNode array = GraphUtil.unproxify(length.array()); + ValueNode cachedValue = state.getReadCache(array, ARRAY_LENGTH_LOCATION, this); + if (cachedValue != null) { + effects.replaceAtUsages(length, cachedValue); + addScalarAlias(length, cachedValue); + deleted = true; + } else { + state.addReadCache(array, ARRAY_LENGTH_LOCATION, length, this); + } } else if (node instanceof MemoryCheckpoint.Single) { METRIC_MEMORYCHECKPOINT.increment(); LocationIdentity identity = ((MemoryCheckpoint.Single) node).getLocationIdentity(); @@ -183,7 +194,7 @@ } } - private void mergeReadCachePhi(PhiNode phi, ResolvedJavaField identity, List states) { + private void mergeReadCachePhi(PhiNode phi, LocationIdentity identity, List states) { ValueNode[] values = new ValueNode[phi.valueCount()]; for (int i = 0; i < phi.valueCount(); i++) { ValueNode value = states.get(i).getReadCache(phi.valueAt(i), identity, PEReadEliminationClosure.this); diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/PartialEscapeClosure.java --- a/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/PartialEscapeClosure.java Fri Apr 25 16:21:07 2014 +0200 +++ b/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/PartialEscapeClosure.java Mon Apr 28 11:18:15 2014 +0200 @@ -26,6 +26,7 @@ import com.oracle.graal.api.code.*; import com.oracle.graal.api.meta.*; +import com.oracle.graal.compiler.common.type.*; import com.oracle.graal.debug.*; import com.oracle.graal.graph.*; import com.oracle.graal.nodes.*; @@ -35,7 +36,6 @@ import com.oracle.graal.nodes.java.*; import com.oracle.graal.nodes.spi.*; import com.oracle.graal.nodes.spi.Virtualizable.EscapeState; -import com.oracle.graal.nodes.type.*; import com.oracle.graal.nodes.virtual.*; import com.oracle.graal.phases.schedule.*; import com.oracle.graal.phases.util.*; @@ -132,78 +132,75 @@ } private void processNodeWithState(NodeWithState nodeWithState, final BlockT state, final GraphEffectList effects) { - for (Node input : nodeWithState.asNode().inputs()) { - if (input instanceof FrameState) { - FrameState frameState = (FrameState) input; - if (frameState.usages().count() > 1) { - FrameState copy = (FrameState) frameState.copyWithInputs(); - nodeWithState.asNode().replaceFirstInput(frameState, copy); - frameState = copy; - } - final Set virtual = new ArraySet<>(); - frameState.applyToNonVirtual(new NodeClosure() { + for (FrameState frameState : nodeWithState.states()) { + if (frameState.usages().count() > 1) { + FrameState copy = (FrameState) frameState.copyWithInputs(); + nodeWithState.asNode().replaceFirstInput(frameState, copy); + frameState = copy; + } + final Set virtual = new ArraySet<>(); + frameState.applyToNonVirtual(new NodeClosure() { - @Override - public void apply(Node usage, ValueNode value) { - ObjectState valueObj = getObjectState(state, value); - if (valueObj != null) { - virtual.add(valueObj); - effects.replaceFirstInput(usage, value, valueObj.virtual); - } else if (value instanceof VirtualObjectNode) { - ObjectState virtualObj = null; - for (ObjectState obj : state.getStates()) { - if (value == obj.virtual) { - virtualObj = obj; - break; - } - } - if (virtualObj != null) { - virtual.add(virtualObj); + @Override + public void apply(Node usage, ValueNode value) { + ObjectState valueObj = getObjectState(state, value); + if (valueObj != null) { + virtual.add(valueObj); + effects.replaceFirstInput(usage, value, valueObj.virtual); + } else if (value instanceof VirtualObjectNode) { + ObjectState virtualObj = null; + for (ObjectState obj : state.getStates()) { + if (value == obj.virtual) { + virtualObj = obj; + break; } } - } - }); - for (ObjectState obj : state.getStates()) { - if (obj.isVirtual() && obj.hasLocks()) { - virtual.add(obj); + if (virtualObj != null) { + virtual.add(virtualObj); + } } } + }); + for (ObjectState obj : state.getStates()) { + if (obj.isVirtual() && obj.hasLocks()) { + virtual.add(obj); + } + } - ArrayDeque queue = new ArrayDeque<>(virtual); - while (!queue.isEmpty()) { - ObjectState obj = queue.removeLast(); - if (obj.isVirtual()) { - for (ValueNode field : obj.getEntries()) { - if (field instanceof VirtualObjectNode) { - ObjectState fieldObj = state.getObjectState((VirtualObjectNode) field); - if (fieldObj.isVirtual() && !virtual.contains(fieldObj)) { - virtual.add(fieldObj); - queue.addLast(fieldObj); - } + ArrayDeque queue = new ArrayDeque<>(virtual); + while (!queue.isEmpty()) { + ObjectState obj = queue.removeLast(); + if (obj.isVirtual()) { + for (ValueNode field : obj.getEntries()) { + if (field instanceof VirtualObjectNode) { + ObjectState fieldObj = state.getObjectState((VirtualObjectNode) field); + if (fieldObj.isVirtual() && !virtual.contains(fieldObj)) { + virtual.add(fieldObj); + queue.addLast(fieldObj); } } } } - for (ObjectState obj : virtual) { - EscapeObjectState v; - if (obj.isVirtual()) { - ValueNode[] fieldState = obj.getEntries().clone(); - for (int i = 0; i < fieldState.length; i++) { - ObjectState valueObj = getObjectState(state, fieldState[i]); - if (valueObj != null) { - if (valueObj.isVirtual()) { - fieldState[i] = valueObj.virtual; - } else { - fieldState[i] = valueObj.getMaterializedValue(); - } + } + for (ObjectState obj : virtual) { + EscapeObjectState v; + if (obj.isVirtual()) { + ValueNode[] fieldState = obj.getEntries().clone(); + for (int i = 0; i < fieldState.length; i++) { + ObjectState valueObj = getObjectState(state, fieldState[i]); + if (valueObj != null) { + if (valueObj.isVirtual()) { + fieldState[i] = valueObj.virtual; + } else { + fieldState[i] = valueObj.getMaterializedValue(); } } - v = new VirtualObjectState(obj.virtual, fieldState); - } else { - v = new MaterializedObjectState(obj.virtual, obj.getMaterializedValue()); } - effects.addVirtualMapping(frameState, v); + v = new VirtualObjectState(obj.virtual, fieldState); + } else { + v = new MaterializedObjectState(obj.virtual, obj.getMaterializedValue()); } + effects.addVirtualMapping(frameState, v); } } } diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/PartialEscapePhase.java --- a/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/PartialEscapePhase.java Fri Apr 25 16:21:07 2014 +0200 +++ b/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/PartialEscapePhase.java Mon Apr 28 11:18:15 2014 +0200 @@ -22,7 +22,7 @@ */ package com.oracle.graal.virtual.phases.ea; -import static com.oracle.graal.phases.GraalOptions.*; +import static com.oracle.graal.compiler.common.GraalOptions.*; import static com.oracle.graal.virtual.phases.ea.PartialEscapePhase.Options.*; import java.util.*; diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/ReadEliminationClosure.java --- a/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/ReadEliminationClosure.java Fri Apr 25 16:21:07 2014 +0200 +++ b/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/ReadEliminationClosure.java Mon Apr 28 11:18:15 2014 +0200 @@ -27,12 +27,12 @@ import java.util.*; import com.oracle.graal.api.meta.*; +import com.oracle.graal.compiler.common.type.*; import com.oracle.graal.graph.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.cfg.*; import com.oracle.graal.nodes.extended.*; import com.oracle.graal.nodes.java.*; -import com.oracle.graal.nodes.type.*; import com.oracle.graal.nodes.util.*; import com.oracle.graal.phases.schedule.*; import com.oracle.graal.virtual.phases.ea.ReadEliminationBlockState.CacheEntry; diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/VirtualUtil.java --- a/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/VirtualUtil.java Fri Apr 25 16:21:07 2014 +0200 +++ b/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/VirtualUtil.java Mon Apr 28 11:18:15 2014 +0200 @@ -22,11 +22,12 @@ */ package com.oracle.graal.virtual.phases.ea; -import static com.oracle.graal.phases.GraalOptions.*; +import static com.oracle.graal.compiler.common.GraalOptions.*; import java.util.*; import com.oracle.graal.api.meta.*; +import com.oracle.graal.compiler.common.*; import com.oracle.graal.debug.*; import com.oracle.graal.graph.*; import com.oracle.graal.nodes.*; diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/VirtualizerToolImpl.java --- a/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/VirtualizerToolImpl.java Fri Apr 25 16:21:07 2014 +0200 +++ b/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/VirtualizerToolImpl.java Mon Apr 28 11:18:15 2014 +0200 @@ -22,7 +22,7 @@ */ package com.oracle.graal.virtual.phases.ea; -import static com.oracle.graal.phases.GraalOptions.*; +import static com.oracle.graal.compiler.common.GraalOptions.*; import java.util.*; diff -r 3dde8d8c95b8 -r 40d0022115ee 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 Fri Apr 25 16:21:07 2014 +0200 +++ b/graal/com.oracle.graal.word/src/com/oracle/graal/word/Word.java Mon Apr 28 11:18:15 2014 +0200 @@ -22,13 +22,14 @@ */ package com.oracle.graal.word; -import static com.oracle.graal.graph.UnsafeAccess.*; +import static com.oracle.graal.compiler.common.UnsafeAccess.*; import java.lang.annotation.*; import com.oracle.graal.api.code.*; import com.oracle.graal.api.meta.*; -import com.oracle.graal.graph.*; +import com.oracle.graal.compiler.common.*; +import com.oracle.graal.compiler.common.calc.*; import com.oracle.graal.nodes.HeapAccess.BarrierType; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.calc.*; diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.word/src/com/oracle/graal/word/nodes/SnippetLocationNode.java --- a/graal/com.oracle.graal.word/src/com/oracle/graal/word/nodes/SnippetLocationNode.java Fri Apr 25 16:21:07 2014 +0200 +++ b/graal/com.oracle.graal.word/src/com/oracle/graal/word/nodes/SnippetLocationNode.java Mon Apr 28 11:18:15 2014 +0200 @@ -26,12 +26,14 @@ import com.oracle.graal.api.meta.*; import com.oracle.graal.api.replacements.*; +import com.oracle.graal.compiler.common.*; +import com.oracle.graal.compiler.common.type.*; import com.oracle.graal.graph.*; import com.oracle.graal.graph.spi.*; +import com.oracle.graal.lir.gen.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.extended.*; import com.oracle.graal.nodes.spi.*; -import com.oracle.graal.nodes.type.*; /** * Location node that can be used inside a snippet without having the elements (including the @@ -107,7 +109,7 @@ } @Override - public Value generateAddress(NodeLIRBuilderTool gen, Value base) { + public Value generateAddress(NodeMappableLIRBuilder builder, LIRGeneratorTool gen, Value base) { throw new GraalInternalError("locationIdentity must be a constant so that this node can be canonicalized: " + locationIdentity); } diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.word/src/com/oracle/graal/word/nodes/WordCastNode.java --- a/graal/com.oracle.graal.word/src/com/oracle/graal/word/nodes/WordCastNode.java Fri Apr 25 16:21:07 2014 +0200 +++ b/graal/com.oracle.graal.word/src/com/oracle/graal/word/nodes/WordCastNode.java Mon Apr 28 11:18:15 2014 +0200 @@ -23,11 +23,11 @@ package com.oracle.graal.word.nodes; import com.oracle.graal.api.meta.*; +import com.oracle.graal.compiler.common.type.*; import com.oracle.graal.graph.*; import com.oracle.graal.graph.spi.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.spi.*; -import com.oracle.graal.nodes.type.*; import com.oracle.graal.word.phases.*; /** diff -r 3dde8d8c95b8 -r 40d0022115ee 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 Fri Apr 25 16:21:07 2014 +0200 +++ b/graal/com.oracle.graal.word/src/com/oracle/graal/word/phases/WordTypeRewriterPhase.java Mon Apr 28 11:18:15 2014 +0200 @@ -28,6 +28,9 @@ import com.oracle.graal.api.meta.*; import com.oracle.graal.api.replacements.*; +import com.oracle.graal.compiler.common.*; +import com.oracle.graal.compiler.common.calc.*; +import com.oracle.graal.compiler.common.type.*; import com.oracle.graal.graph.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.HeapAccess.BarrierType; @@ -141,7 +144,7 @@ * own and not in the stamp, {@link #changeToWord} does not perform all necessary changes. */ protected void rewriteAccessIndexed(StructuredGraph graph, AccessIndexedNode node) { - ResolvedJavaType arrayType = ObjectStamp.typeOrNull(node.array()); + ResolvedJavaType arrayType = StampTool.typeOrNull(node.array()); /* * There are cases where the array does not have a known type yet, i.e., the type is null. * In that case we assume it is not a word type. @@ -231,7 +234,7 @@ case WRITE: case INITIALIZE: { assert arguments.size() == 3 || arguments.size() == 4; - Kind writeKind = asKind(targetMethod.getSignature().getParameterType(Modifier.isStatic(targetMethod.getModifiers()) ? 2 : 1, targetMethod.getDeclaringClass())); + Kind writeKind = asKind(targetMethod.getSignature().getParameterType(targetMethod.isStatic() ? 2 : 1, targetMethod.getDeclaringClass())); LocationNode location; if (arguments.size() == 3) { location = makeLocation(graph, arguments.get(1), writeKind, LocationIdentity.ANY_LOCATION); @@ -379,7 +382,7 @@ * The read must not float outside its block otherwise it may float above an explicit zero * check on its base address. */ - read.setGuard(AbstractBeginNode.prevBegin(invoke.asNode())); + read.setGuard(BeginNode.prevBegin(invoke.asNode())); return read; } @@ -400,7 +403,7 @@ } protected boolean isWord(ValueNode node) { - return isWord(ObjectStamp.typeOrNull(node)); + return isWord(StampTool.typeOrNull(node)); } protected boolean isWord(ResolvedJavaType type) { diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.graal.word/src/com/oracle/graal/word/phases/WordTypeVerificationPhase.java --- a/graal/com.oracle.graal.word/src/com/oracle/graal/word/phases/WordTypeVerificationPhase.java Fri Apr 25 16:21:07 2014 +0200 +++ b/graal/com.oracle.graal.word/src/com/oracle/graal/word/phases/WordTypeVerificationPhase.java Mon Apr 28 11:18:15 2014 +0200 @@ -22,10 +22,9 @@ */ package com.oracle.graal.word.phases; -import java.lang.reflect.*; - import com.oracle.graal.api.meta.*; import com.oracle.graal.api.replacements.*; +import com.oracle.graal.compiler.common.*; import com.oracle.graal.graph.*; import com.oracle.graal.graph.Node.NodeIntrinsic; import com.oracle.graal.nodes.*; @@ -109,7 +108,7 @@ if (method.getAnnotation(NodeIntrinsic.class) == null) { Invoke invoke = (Invoke) callTarget.usages().first(); NodeInputList arguments = callTarget.arguments(); - boolean isStatic = Modifier.isStatic(method.getModifiers()); + boolean isStatic = method.isStatic(); int argc = 0; if (!isStatic) { ValueNode receiver = arguments.get(argc); diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/OnAdoptTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/OnAdoptTest.java Mon Apr 28 11:18:15 2014 +0200 @@ -0,0 +1,130 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.truffle.api.test; + +import org.junit.*; + +import com.oracle.truffle.api.*; +import com.oracle.truffle.api.frame.*; +import com.oracle.truffle.api.nodes.*; + +/** + *

Inserting Extra Nodes into the AST Transparently

+ * + *

+ * The {@link Node} class provides a callback that is invoked whenever a node is adopted in an AST + * by insertion or replacement. Node classes can override the {@code onAdopt()} method to run extra + * functionality upon adoption. + *

+ * + *

+ * This test demonstrates how node instances of a specific class can be automatically wrapped in + * extra nodes when they are inserted into the AST. + *

+ */ +public class OnAdoptTest { + + static class Root extends RootNode { + + @Child private Base child1; + @Child private Base child2; + + public Root(Base child1, Base child2) { + super(null); + this.child1 = child1; + this.child2 = child2; + } + + @Override + public Object execute(VirtualFrame frame) { + return child1.executeInt(frame) + child2.executeInt(frame); + } + + } + + abstract static class Base extends Node { + public abstract int executeInt(VirtualFrame frame); + } + + static class Wrapper extends Base { + + @Child private Base wrappee; + + public Wrapper(Base wrappee) { + this.wrappee = wrappee; + } + + @Override + public int executeInt(VirtualFrame frame) { + return 1 + wrappee.executeInt(frame); + } + + } + + abstract static class GenBase extends Base { + + private final int k; + + public GenBase(int k) { + this.k = k; + } + + @Override + public int executeInt(VirtualFrame frame) { + return k; + } + + } + + static class Gen extends GenBase { + public Gen(int k) { + super(k); + } + } + + static class GenWrapped extends GenBase { + + public GenWrapped(int k) { + super(k); + } + + @Override + protected void onAdopt() { + Wrapper w = new Wrapper(this); + this.replace(w); + } + + } + + @Test + public void testOnInsert() { + TruffleRuntime runtime = Truffle.getRuntime(); + Base b1 = new Gen(11); + Base b2 = new GenWrapped(11); + Root r = new Root(b1, b2); + CallTarget ct = runtime.createCallTarget(r); + Object result = ct.call(); + Assert.assertEquals(23, result); + } + +} diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/RootNodeTest.java --- a/graal/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/RootNodeTest.java Fri Apr 25 16:21:07 2014 +0200 +++ b/graal/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/RootNodeTest.java Mon Apr 28 11:18:15 2014 +0200 @@ -30,7 +30,7 @@ /** *

Creating a Root Node

- * + * *

* A Truffle root node is the entry point into a Truffle tree that represents a guest language * method. It contains a {@link RootNode#execute(VirtualFrame)} method that can return a @@ -38,9 +38,9 @@ * must however never be called directly. Instead, the Truffle runtime must be used to create a * {@link CallTarget} object from a root node using the * {@link TruffleRuntime#createCallTarget(RootNode)} method. This call target object can then be - * executed using the {@link CallTarget#call()} method or one of its overloads. + * executed using the {@link CallTarget#call(Object...)} method or one of its overloads. *

- * + * *

* The next part of the Truffle API introduction is at * {@link com.oracle.truffle.api.test.ChildNodeTest}. diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/ThreadSafetyTest.java --- a/graal/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/ThreadSafetyTest.java Fri Apr 25 16:21:07 2014 +0200 +++ b/graal/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/ThreadSafetyTest.java Mon Apr 28 11:18:15 2014 +0200 @@ -24,7 +24,6 @@ import static org.junit.Assert.*; -import java.io.*; import java.util.*; import java.util.concurrent.*; import java.util.concurrent.atomic.*; @@ -50,7 +49,7 @@ RecursiveCallNode callNode = new RecursiveCallNode(new ConstNode(42)); TestRootNode rootNode2 = new TestRootNode(new RewritingNode(new RewritingNode(new RewritingNode(new RewritingNode(new RewritingNode(callNode)))))); final CallTarget target2 = runtime.createCallTarget(rootNode2); - callNode.setCallNode(runtime.createCallNode(target2)); + callNode.setCallNode(runtime.createDirectCallNode(target2)); NodeUtil.verify(rootNode2); testTarget(target1, 47, 1_000_000); @@ -68,8 +67,7 @@ assertEquals(expectedResult, result); ai.incrementAndGet(); } catch (Throwable t) { - PrintStream out = System.out; - out.println(t); + t.printStackTrace(System.out); } } }); @@ -165,7 +163,7 @@ } static class RecursiveCallNode extends ValueNode { - @Child CallNode callNode; + @Child DirectCallNode callNode; @Child private ValueNode valueNode; RecursiveCallNode(ValueNode value) { @@ -182,7 +180,7 @@ } } - void setCallNode(CallNode callNode) { + void setCallNode(DirectCallNode callNode) { this.callNode = insert(callNode); } } diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.truffle.api/src/com/oracle/truffle/api/CallTarget.java --- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/CallTarget.java Fri Apr 25 16:21:07 2014 +0200 +++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/CallTarget.java Mon Apr 28 11:18:15 2014 +0200 @@ -27,9 +27,7 @@ /** * Represents the target of a call. */ -public abstract class CallTarget { - - public static final Object[] NO_ARGUMENTS = new Object[0]; +public interface CallTarget { /** * Calls this target as a root method.. @@ -37,11 +35,5 @@ * @param arguments passed arguments as an object array * @return the return result of the call */ - public abstract Object call(Object[] arguments); - - public final Object call() { - return call(NO_ARGUMENTS); - } - - public abstract void setNeedsMaterializedFrame(); + Object call(Object... arguments); } diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.truffle.api/src/com/oracle/truffle/api/CompilerDirectives.java --- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/CompilerDirectives.java Fri Apr 25 16:21:07 2014 +0200 +++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/CompilerDirectives.java Mon Apr 28 11:18:15 2014 +0200 @@ -84,6 +84,15 @@ } /** + * Returns a boolean value indicating whether the method is executed in the compiled code. + * + * @return {@code false} when executed in the interpreter, {@code true} in compiled code. + */ + public static boolean inCompiledCode() { + return false; + } + + /** * Directive for the compiler that the given runnable should only be executed in the interpreter * and ignored in the compiled code. * diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.truffle.api/src/com/oracle/truffle/api/ExecutionContext.java --- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/ExecutionContext.java Fri Apr 25 16:21:07 2014 +0200 +++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/ExecutionContext.java Mon Apr 28 11:18:15 2014 +0200 @@ -24,11 +24,12 @@ */ package com.oracle.truffle.api; -import com.oracle.truffle.api.debug.*; +import com.oracle.truffle.api.instrument.*; import com.oracle.truffle.api.source.*; /** - * Information about the runtime context of a Truffle program. + * Access to information and basic services in the runtime context for a Truffle-implemented guest + * language. *

* Disclaimer: this interface is under development and will change. */ @@ -46,8 +47,20 @@ SourceManager getSourceManager(); /** - * Gets access to debugging services. Returns an inert instance if no services installed. + * Gets access to AST instrumentation services. + */ + Instrumentation instrumentation(); + + /** + * Access to information visualization services for the specific language. */ - DebugContext getDebugContext(); + Visualizer visualizer(); + /** + * Add instrumentation to subsequently constructed Truffle ASTs for the guest language; every + * one added will have the opportunity to add instrumentation. + * + * @throws IllegalArgumentException if prober not usable for the guest language. + */ + void addNodeProber(ASTNodeProber nodeProber); } diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.truffle.api/src/com/oracle/truffle/api/RootCallTarget.java --- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/RootCallTarget.java Fri Apr 25 16:21:07 2014 +0200 +++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/RootCallTarget.java Mon Apr 28 11:18:15 2014 +0200 @@ -24,38 +24,13 @@ */ package com.oracle.truffle.api; -import com.oracle.truffle.api.frame.*; import com.oracle.truffle.api.nodes.*; /** * Represents the target of a call to a {@link RootNode}, i.e., to another tree of nodes. Instances * of this class can be created using {@link TruffleRuntime#createCallTarget(RootNode)}. */ -public abstract class RootCallTarget extends CallTarget { - - private final RootNode rootNode; - - public RootCallTarget(RootNode function) { - this.rootNode = function; - this.rootNode.setCallTarget(this); - this.rootNode.adoptChildren(); - } +public interface RootCallTarget extends CallTarget { - @Override - public String toString() { - return rootNode.toString(); - } - - public final RootNode getRootNode() { - return rootNode; - } - - protected final Object callProxy(VirtualFrame frame) { - try { - return getRootNode().execute(frame); - } finally { - // this assertion is needed to keep the values from being cleared as non-live locals - assert frame != null && this != null; - } - } + RootNode getRootNode(); } diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.truffle.api/src/com/oracle/truffle/api/Source.java --- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/Source.java Fri Apr 25 16:21:07 2014 +0200 +++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/Source.java Mon Apr 28 11:18:15 2014 +0200 @@ -34,12 +34,21 @@ /** * Returns the name of this resource holding a guest language program. An example would be the * name of a guest language source code file. - * + * * @return the name of the guest language program */ String getName(); /** + * Returns a short version of the name of the resource holding a guest language program (as + * described in @getName). For example, this could be just the name of the file, rather than a + * full path. + * + * @return the short name of the guest language program + */ + String getShortName(); + + /** * The normalized, canonical name of the file. */ String getPath(); diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.truffle.api/src/com/oracle/truffle/api/SourceSection.java --- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/SourceSection.java Fri Apr 25 16:21:07 2014 +0200 +++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/SourceSection.java Mon Apr 28 11:18:15 2014 +0200 @@ -31,21 +31,21 @@ /** * Returns the object representing the source program that contains this section. - * + * * @return the source object */ Source getSource(); /** * Returns 1-based line number of the first character in this source section (inclusive). - * + * * @return the starting line number */ int getStartLine(); /** * Returns the 1-based column number of the first character in this source section (inclusive). - * + * * @return the starting column number */ int getStartColumn(); @@ -55,7 +55,7 @@ *

* The complete text of the source that contains this section can be retrieved via * {@link Source#getCode()}. - * + * * @return the starting character index */ int getCharIndex(); @@ -65,7 +65,7 @@ *

* The complete text of the source that contains this section can be retrieved via * {@link Source#getCode()}. - * + * * @return the number of characters in the section */ int getCharLength(); @@ -73,42 +73,54 @@ /** * Returns the index of the text position immediately following the last character in the * section. - * + * * @return the end position of the section */ int getCharEndIndex(); /** * Returns the identifier of this source section that is used for printing the section. - * + * * @return the identifier of the section */ String getIdentifier(); /** * Returns text of the code represented by this source section. - * + * * @return the code as a String object */ String getCode(); /** + * Returns a short description of the source section, using just the file name, rather than its + * full path. + * + * @return a short description of the source section + */ + String getShortDescription(); + + /** * Singleton instance with no content. */ SourceSection NULL = new NullSourceSection() { + @Override public Source getSource() { return null; } + @Override public int getStartLine() { return 0; } + @Override public int getStartColumn() { return 0; } + @Override public int getCharIndex() { return 0; } @@ -118,18 +130,26 @@ return 0; } + @Override public int getCharEndIndex() { return 0; } + @Override public String getIdentifier() { return null; } + @Override public String getCode() { return null; } + @Override + public String getShortDescription() { + return "short"; + } + }; } diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.truffle.api/src/com/oracle/truffle/api/TruffleRuntime.java --- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/TruffleRuntime.java Fri Apr 25 16:21:07 2014 +0200 +++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/TruffleRuntime.java Mon Apr 28 11:18:15 2014 +0200 @@ -25,7 +25,6 @@ package com.oracle.truffle.api; import com.oracle.truffle.api.frame.*; -import com.oracle.truffle.api.impl.*; import com.oracle.truffle.api.nodes.*; /** @@ -51,7 +50,20 @@ */ RootCallTarget createCallTarget(RootNode rootNode); - CallNode createCallNode(CallTarget target); + /** + * Creates a new runtime specific version of {@link DirectCallNode}. + * + * @param target the direct {@link CallTarget} to call + * @return the new call node + */ + DirectCallNode createDirectCallNode(CallTarget target); + + /** + * Creates a new runtime specific version of {@link IndirectCallNode}. + * + * @return the new call node + */ + IndirectCallNode createIndirectCallNode(); /** * Creates a new assumption object that can be checked and invalidated. @@ -94,9 +106,7 @@ /** * Accesses the current stack, i.e., the contents of the {@link Frame}s and the associated - * {@link CallTarget}s. For this functionality to work each call needs to go through - * {@link DefaultCallNode#callProxy(MaterializedFrameNotify, CallTarget, VirtualFrame, Object[])} - * instead of calling {@link CallTarget#call(Object[])} directly. + * {@link CallTarget}s. * * @return a lazy collection of {@link FrameInstance}. */ @@ -107,4 +117,5 @@ * important to note that this {@link FrameInstance} supports only slow path access. */ FrameInstance getCurrentFrame(); + } diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.truffle.api/src/com/oracle/truffle/api/debug/ASTPrinter.java --- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/debug/ASTPrinter.java Fri Apr 25 16:21:07 2014 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,65 +0,0 @@ -/* - * Copyright (c) 2013, 2014, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * 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.truffle.api.debug; - -import java.io.*; - -import com.oracle.truffle.api.nodes.*; - -/** - * Language-agnostic access to AST-based debugging support. - *

- * WARNING: this interface is under development and will change substantially. - */ -public interface ASTPrinter { - - /** - * Prints a textual AST display, one line per node, with nesting. - * - * @param p - * @param node the root node of the display. - * @param maxDepth the maximum number of levels to print below the root - * @param markNode a node to mark with a textual arrow prefix, if present. - */ - void printTree(PrintWriter p, Node node, int maxDepth, Node markNode); - - /** - * Creates a textual AST display, one line per node, with nesting. - * - * @param node the root node of the display. - * @param maxDepth the maximum number of levels to print below the root - * @param markNode a node to mark with a textual arrow prefix, if present. - */ - String printTreeToString(Node node, int maxDepth, Node markNode); - - /** - * Creates a textual AST display, one line per node, with nesting. - * - * @param node the root node of the display. - * @param maxDepth the maximum number of levels to print below the root - */ - String printTreeToString(Node node, int maxDepth); - -} diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.truffle.api/src/com/oracle/truffle/api/debug/DebugContext.java --- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/debug/DebugContext.java Fri Apr 25 16:21:07 2014 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,72 +0,0 @@ -/* - * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * 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.truffle.api.debug; - -import com.oracle.truffle.api.*; -import com.oracle.truffle.api.frame.*; -import com.oracle.truffle.api.nodes.*; -import com.oracle.truffle.api.nodes.instrument.*; - -/** - * Access to the suite of facilities available when debugging is enabled. - */ -public interface DebugContext { - - /** - * Access to the Truffle execution context being debugged. - */ - ExecutionContext getContext(); - - /** - * Access to the appropriate implementation of AST node instrumentation. - */ - NodeInstrumenter getNodeInstrumenter(); - - /** - * Access to the management of breakpoints, notifications, etc. - */ - DebugManager getDebugManager(); - - /** - * Gets a printer for Truffle ASTs helpful for debugging guest language implementations. - */ - ASTPrinter getASTPrinter(); - - /** - * Converts a value in the guest language to a display string. - */ - String displayValue(Object value); - - /** - * Converts a slot identifier in the guest language to a display string. - */ - String displayIdentifier(FrameSlot slot); - - /** - * Invokes appropriate debugging action when Truffle execution halts. - */ - void executionHalted(Node node, MaterializedFrame frame); - -} diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.truffle.api/src/com/oracle/truffle/api/debug/DebugManager.java --- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/debug/DebugManager.java Fri Apr 25 16:21:07 2014 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,71 +0,0 @@ -/* - * Copyright (c) 2013, 2014, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * 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.truffle.api.debug; - -import com.oracle.truffle.api.*; -import com.oracle.truffle.api.frame.*; -import com.oracle.truffle.api.nodes.*; -import com.oracle.truffle.api.nodes.instrument.*; -import com.oracle.truffle.api.nodes.instrument.InstrumentationProbeNode.ProbeChain; - -/** - * Language-agnostic access to AST-based debugging support. - *

- * Disclaimer: this interface is under development and will change. - */ -public interface DebugManager { - - /** - * Informs the {@link DebugManager} that the Guest Language runtime is starting to load a - * source. Care should be taken to ensure that under any circumstance there is always a - * following call to {@link #notifyFinishedLoading(Source)} with the same argument. - */ - void notifyStartLoading(Source source); - - /** - * Informs the {@link DebugManager} that the Guest Language runtime has finished loading a - * source. Care should be taken to ensure that under any circumstance there is always a prior - * call to {@link #notifyStartLoading(Source)} with the same argument. - */ - void notifyFinishedLoading(Source source); - - /** - * Return a reference to the (canonical) instrumentation site associated with a particular - * source code location; this site will have effect on any Truffle/AST implementation - * corresponding to the source location, even if the AST is copied multiple times. - */ - ProbeChain getProbeChain(SourceSection sourceSection); - - /** - * Informs the {@link DebugManager} that Truffle execution has halted; execution will resume - * when this method returns. - * - * @param astNode a guest language AST node that represents the current execution site, assumed - * not to be any kind of {@link InstrumentationNode}, - * @param frame execution frame at the site where execution suspended - */ - void haltedAt(Node astNode, MaterializedFrame frame); - -} diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.truffle.api/src/com/oracle/truffle/api/debug/DefaultDebugManager.java --- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/debug/DefaultDebugManager.java Fri Apr 25 16:21:07 2014 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,111 +0,0 @@ -/* - * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * 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.truffle.api.debug; - -import java.util.*; - -import com.oracle.truffle.api.*; -import com.oracle.truffle.api.frame.*; -import com.oracle.truffle.api.nodes.*; -import com.oracle.truffle.api.nodes.instrument.InstrumentationProbeNode.ProbeChain; -import com.oracle.truffle.api.source.*; - -/** - * A minimal, language-agnostic implementation that tracks loaded sources, and keeps maps describing - * what locations in the source have instrumentation available. This implementation will do nothing - * unless there are calls to it during AST construction, notably {@link #notifyStartLoading(Source)} - * and {@link #notifyFinishedLoading(Source)} and there are at least some AST nodes being - * instrumented. - */ -public class DefaultDebugManager implements DebugManager { - - private final Set loadedSources = new HashSet<>(); - - private Source beingLoaded = null; - - /** - * Map: SourceSection ==> probe chain associated with that source section in an AST. - */ - private final Map srcToProbeChain = new HashMap<>(); - - /** - * Map: Source lines ==> probe chains associated with source sections starting on the line. - */ - private final Map> lineToProbeChains = new HashMap<>(); - - private final ExecutionContext context; - - public DefaultDebugManager(ExecutionContext context) { - this.context = context; - } - - /** - * Gets the {@linkplain ProbeChain probe} associated with a particular {@link SourceSection - * source location}, creating a new one if needed. There should only be one probe associated - * with each {@linkplain SourceSection source location}. - */ - public ProbeChain getProbeChain(SourceSection sourceSection) { - assert sourceSection != null; - assert sourceSection.getSource().equals(beingLoaded); - - ProbeChain probeChain = srcToProbeChain.get(sourceSection); - - if (probeChain != null) { - return probeChain; - } - probeChain = new ProbeChain(context, sourceSection, null); - - // Register new ProbeChain by unique SourceSection - srcToProbeChain.put(sourceSection, probeChain); - - // Register new ProbeChain by source line, there may be more than one - // Create line location for map key - final SourceLineLocation lineLocation = new SourceLineLocation(sourceSection.getSource(), sourceSection.getStartLine()); - - Set probeChains = lineToProbeChains.get(lineLocation); - if (probeChains == null) { - probeChains = new HashSet<>(); - lineToProbeChains.put(lineLocation, probeChains); - } - probeChains.add(probeChain); - - return probeChain; - } - - public void notifyStartLoading(Source source) { - assert beingLoaded == null; - beingLoaded = source; - } - - public void notifyFinishedLoading(Source source) { - assert source == beingLoaded; - loadedSources.add(source); - beingLoaded = null; - } - - public void haltedAt(Node astNode, MaterializedFrame frame) { - } - -} diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.truffle.api/src/com/oracle/truffle/api/debug/KillException.java --- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/debug/KillException.java Fri Apr 25 16:21:07 2014 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,35 +0,0 @@ -/* - * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * 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.truffle.api.debug; - -import com.oracle.truffle.api.nodes.*; - -/** - * Controls breaking out of an execution context, such as a shell or eval. - */ -public final class KillException extends ControlFlowException { - - private static final long serialVersionUID = 3163641880088766957L; -} diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.truffle.api/src/com/oracle/truffle/api/debug/QuitException.java --- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/debug/QuitException.java Fri Apr 25 16:21:07 2014 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,35 +0,0 @@ -/* - * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * 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.truffle.api.debug; - -import com.oracle.truffle.api.nodes.*; - -/** - * Controls breaking out of all executions and ending Truffle execution. - */ -public final class QuitException extends ControlFlowException { - - private static final long serialVersionUID = -4301115629772778413L; -} diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.truffle.api/src/com/oracle/truffle/api/frame/FrameInstance.java --- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/frame/FrameInstance.java Fri Apr 25 16:21:07 2014 +0200 +++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/frame/FrameInstance.java Mon Apr 28 11:18:15 2014 +0200 @@ -40,7 +40,7 @@ boolean isVirtualFrame(); - CallNode getCallNode(); + Node getCallNode(); CallTarget getCallTarget(); } diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.truffle.api/src/com/oracle/truffle/api/impl/AbstractExecutionContext.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/impl/AbstractExecutionContext.java Mon Apr 28 11:18:15 2014 +0200 @@ -0,0 +1,91 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * 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.truffle.api.impl; + +import com.oracle.truffle.api.*; +import com.oracle.truffle.api.instrument.*; +import com.oracle.truffle.api.instrument.impl.*; +import com.oracle.truffle.api.source.*; + +public abstract class AbstractExecutionContext implements ExecutionContext { + + private final SourceManager sourceManager = new SourceManager(); + private final Instrumentation instrumentation; + private Visualizer visualizer = new DefaultVisualizer(); + protected ASTProber astProber = null; + + protected AbstractExecutionContext() { + this.instrumentation = InstrumentationFactory.create(this); + } + + public final SourceManager getSourceManager() { + return sourceManager; + } + + public final Instrumentation instrumentation() { + return instrumentation; + } + + public Visualizer visualizer() { + return visualizer; + } + + public void addNodeProber(ASTNodeProber nodeProber) { + if (astProber == null) { + throw new IllegalStateException("No ASTProber installed in context"); + } + astProber.addNodeProber(nodeProber); + } + + /** + * Assign guest language-specific visualization support for tools. This must be assigned outside + * the implementation context to avoid build circularities. + */ + public void setVisualizer(Visualizer visualizer) { + this.visualizer = visualizer; + } + + /** + * Assigns a guest language-specific manager for using {@link ASTNodeProber}s added by tools to + * instrument ASTs with {@link Probe}s at specified nodes. This must be assigned outside the + * implementation context to avoid build circularities. It must also be set before any + * instrumentation probe implementations are assigned. + */ + public void setASTProber(ASTProber astProber) { + this.astProber = astProber; + } + + /** + * Gets a guest language-specific {@link ASTNodeProber} that will apply all that have been + * added; {@code null} if no instrumentation in AST. + */ + public ASTNodeProber getCombinedNodeProber() { + return astProber == null ? null : astProber.getCombinedNodeProber(); + } + + public abstract void setInstrumentEventListener(InstrumentEventListener listener); + + public abstract InstrumentEventListener getInstrumentEventListener(); +} diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.truffle.api/src/com/oracle/truffle/api/impl/DefaultCallNode.java --- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/impl/DefaultCallNode.java Fri Apr 25 16:21:07 2014 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,101 +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. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * 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.truffle.api.impl; - -import com.oracle.truffle.api.*; -import com.oracle.truffle.api.CompilerDirectives.*; -import com.oracle.truffle.api.frame.*; -import com.oracle.truffle.api.frame.FrameInstance.*; -import com.oracle.truffle.api.nodes.*; - -public class DefaultCallNode extends CallNode implements MaterializedFrameNotify { - - @CompilationFinal private FrameAccess outsideFrameAccess = FrameAccess.NONE; - - public DefaultCallNode(CallTarget target) { - super(target); - } - - @Override - public Object call(VirtualFrame frame, Object[] arguments) { - return callProxy(this, getCurrentCallTarget(), frame, arguments); - } - - public static Object callProxy(MaterializedFrameNotify notify, CallTarget callTarget, VirtualFrame frame, Object[] arguments) { - try { - if (notify.getOutsideFrameAccess() != FrameAccess.NONE) { - CompilerDirectives.materialize(frame); - } - return callTarget.call(arguments); - } finally { - // this assertion is needed to keep the values from being cleared as non-live locals - assert notify != null & callTarget != null & frame != null; - } - } - - @Override - public FrameAccess getOutsideFrameAccess() { - return outsideFrameAccess; - } - - @Override - public void setOutsideFrameAccess(FrameAccess outsideFrameAccess) { - this.outsideFrameAccess = outsideFrameAccess; - } - - @Override - public void inline() { - } - - @Override - public CallTarget getSplitCallTarget() { - return null; - } - - @Override - public boolean split() { - return false; - } - - @Override - public boolean isSplittable() { - return false; - } - - @Override - public boolean isInlined() { - return false; - } - - @Override - public boolean isInlinable() { - return false; - } - - @Override - public String toString() { - return (getParent() != null ? getParent().toString() : super.toString()) + " call " + getCurrentCallTarget().toString(); - } -} diff -r 3dde8d8c95b8 -r 40d0022115ee 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 Fri Apr 25 16:21:07 2014 +0200 +++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/impl/DefaultCallTarget.java Mon Apr 28 11:18:15 2014 +0200 @@ -25,7 +25,6 @@ package com.oracle.truffle.api.impl; import com.oracle.truffle.api.*; -import com.oracle.truffle.api.CompilerDirectives.CompilationFinal; import com.oracle.truffle.api.frame.*; import com.oracle.truffle.api.nodes.*; @@ -33,22 +32,28 @@ * This is an implementation-specific class. Do not use or instantiate it. Instead, use * {@link TruffleRuntime#createCallTarget(RootNode)} to create a {@link RootCallTarget}. */ -public class DefaultCallTarget extends RootCallTarget { +public class DefaultCallTarget implements RootCallTarget { + + private final RootNode rootNode; - @CompilationFinal protected boolean needsMaterializedFrame = true; - - protected DefaultCallTarget(RootNode function) { - super(function); + public DefaultCallTarget(RootNode function) { + this.rootNode = function; + this.rootNode.adoptChildren(); + this.rootNode.setCallTarget(this); } @Override - public Object call(Object[] args) { - VirtualFrame frame = new DefaultVirtualFrame(getRootNode().getFrameDescriptor(), args); - return callProxy(frame); + public String toString() { + return rootNode.toString(); + } + + public final RootNode getRootNode() { + return rootNode; } @Override - public void setNeedsMaterializedFrame() { - needsMaterializedFrame = true; + public Object call(Object... args) { + VirtualFrame frame = new DefaultVirtualFrame(getRootNode().getFrameDescriptor(), args); + return getRootNode().execute(frame); } } diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.truffle.api/src/com/oracle/truffle/api/impl/DefaultDirectCallNode.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/impl/DefaultDirectCallNode.java Mon Apr 28 11:18:15 2014 +0200 @@ -0,0 +1,86 @@ +/* + * 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. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * 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.truffle.api.impl; + +import com.oracle.truffle.api.*; +import com.oracle.truffle.api.frame.*; +import com.oracle.truffle.api.nodes.*; + +/** + * This is runtime specific API. Do not use in a guest language. + */ +public final class DefaultDirectCallNode extends DirectCallNode { + + private boolean inliningForced; + + public DefaultDirectCallNode(CallTarget target) { + super(target); + } + + @Override + public Object call(VirtualFrame frame, Object[] arguments) { + return getCurrentCallTarget().call(arguments); + } + + @Override + public void forceInlining() { + inliningForced = true; + } + + @Override + public boolean isInliningForced() { + return inliningForced; + } + + @Override + public CallTarget getSplitCallTarget() { + return null; + } + + @Override + public boolean split() { + return false; + } + + @Override + public boolean isInlined() { + return false; + } + + @Override + public boolean isSplittable() { + return false; + } + + @Override + public boolean isInlinable() { + return false; + } + + @Override + public String toString() { + return (getParent() != null ? getParent().toString() : super.toString()) + " call " + getCurrentCallTarget().toString(); + } +} diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.truffle.api/src/com/oracle/truffle/api/impl/DefaultIndirectCallNode.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/impl/DefaultIndirectCallNode.java Mon Apr 28 11:18:15 2014 +0200 @@ -0,0 +1,41 @@ +/* + * 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. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * 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.truffle.api.impl; + +import com.oracle.truffle.api.*; +import com.oracle.truffle.api.frame.*; +import com.oracle.truffle.api.nodes.*; + +/** + * This is runtime specific API. Do not use in a guest language. + */ +final class DefaultIndirectCallNode extends IndirectCallNode { + + @Override + public Object call(VirtualFrame frame, CallTarget target, Object[] arguments) { + return target.call(arguments); + } + +} diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.truffle.api/src/com/oracle/truffle/api/impl/DefaultSourceSection.java --- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/impl/DefaultSourceSection.java Fri Apr 25 16:21:07 2014 +0200 +++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/impl/DefaultSourceSection.java Mon Apr 28 11:18:15 2014 +0200 @@ -53,7 +53,7 @@ * a character index. The (row,column) coordinates of a newline character should never appear in * a text section. *

- * + * * @param source object representing the complete source program that contains this section * @param identifier an identifier used when printing the section * @param startLine the 1-based number of the start line of the section @@ -102,6 +102,10 @@ return getSource().getCode().substring(charIndex, charIndex + charLength); } + public final String getShortDescription() { + return String.format("%s:%d", source.getShortName(), startLine); + } + @Override public String toString() { return String.format("%s:%d", source.getName(), startLine); diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.truffle.api/src/com/oracle/truffle/api/impl/DefaultTruffleRuntime.java --- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/impl/DefaultTruffleRuntime.java Fri Apr 25 16:21:07 2014 +0200 +++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/impl/DefaultTruffleRuntime.java Mon Apr 28 11:18:15 2014 +0200 @@ -53,8 +53,12 @@ return new DefaultCallTarget(rootNode); } - public CallNode createCallNode(CallTarget target) { - return new DefaultCallNode(target); + public DirectCallNode createDirectCallNode(CallTarget target) { + return new DefaultDirectCallNode(target); + } + + public IndirectCallNode createIndirectCallNode() { + return new DefaultIndirectCallNode(); } @Override diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.truffle.api/src/com/oracle/truffle/api/impl/MaterializedFrameNotify.java --- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/impl/MaterializedFrameNotify.java Fri Apr 25 16:21:07 2014 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,34 +0,0 @@ -/* - * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * 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.truffle.api.impl; - -import com.oracle.truffle.api.frame.FrameInstance.*; - -public interface MaterializedFrameNotify { - - FrameAccess getOutsideFrameAccess(); - - void setOutsideFrameAccess(FrameAccess outsideFrameAccess); -} diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/ASTNodeProber.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/ASTNodeProber.java Mon Apr 28 11:18:15 2014 +0200 @@ -0,0 +1,63 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * 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.truffle.api.instrument; + +import com.oracle.truffle.api.nodes.*; + +/** + * Implementation of a policy for instrumenting inserting a {@link Probe} at a Truffle AST + * node. + *

+ * Note that this interface is guest language agnostic, but current extensions are + * language-specific. This will be revisited. + *

+ * Disclaimer: experimental interface under development. Really! + */ +public interface ASTNodeProber { + + /** + * Optionally applies instrumentation at a Truffle AST node, depending on guest + * language characteristics and use-case policy. + *

    + *
  • if no instrumentation is to be applied, returns the AST node unmodified;
  • + *
  • if an AST node is to be instrumented, then returns a newly created {@link Wrapper} that + * decorates the AST node and notifies an associated {@link Probe} of all + * {@link ExecutionEvents} at the wrapped AST node.
  • + *
  • if the argument is itself a {@link Wrapper}, i.e. if the AST node at this site has + * already been wrapped, then the wrapper is returned (with the possible addition of a + * {@linkplain PhylumTag tag}).
  • + *
+ * + * @param astNode an AST node to which instrumentation might be applied + * @param tag an optional category directing how the node, if instrumented, should be perceived + * by tool users + * @param args additional arguments for instrumentation specific to a particular guest language + * @return if no instrumentation should be applied or if the node is a {@link Wrapper} then the + * unmodified node; otherwise a newly created {@link Wrapper} (whose child + * {@code astNode}) with an associated {@link Probe} . + */ + + Node probeAs(Node astNode, PhylumTag tag, Object... args); +} diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/ASTPrinter.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/ASTPrinter.java Mon Apr 28 11:18:15 2014 +0200 @@ -0,0 +1,65 @@ +/* + * Copyright (c) 2013, 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * 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.truffle.api.instrument; + +import java.io.*; + +import com.oracle.truffle.api.nodes.*; + +/** + * Language-agnostic access to AST-based debugging support. + *

+ * WARNING: this interface is under development and will change substantially. + */ +public interface ASTPrinter { + + /** + * Prints a textual AST display, one line per node, with nesting. + * + * @param p + * @param node the root node of the display. + * @param maxDepth the maximum number of levels to print below the root + * @param markNode a node to mark with a textual arrow prefix, if present. + */ + void printTree(PrintWriter p, Node node, int maxDepth, Node markNode); + + /** + * Creates a textual AST display, one line per node, with nesting. + * + * @param node the root node of the display. + * @param maxDepth the maximum number of levels to print below the root + * @param markNode a node to mark with a textual arrow prefix, if present. + */ + String printTreeToString(Node node, int maxDepth, Node markNode); + + /** + * Creates a textual AST display, one line per node, with nesting. + * + * @param node the root node of the display. + * @param maxDepth the maximum number of levels to print below the root + */ + String printTreeToString(Node node, int maxDepth); + +} diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/ASTProber.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/ASTProber.java Mon Apr 28 11:18:15 2014 +0200 @@ -0,0 +1,44 @@ +/* + * Copyright (c) 2013, 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * 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.truffle.api.instrument; + +/** + * Implementation of a policy for instrumenting Truffle ASTs with {@link Probe}s at + * particular nodes by inserting node {@link Wrapper}s. + *

+ * Disclaimer: experimental interface under development. + */ +public interface ASTProber { + + // TODO (mlvdv) This is a provisional interface, more of a marker really + // TODO (mlvdv) AST probing should eventually be done with visitors. + + void addNodeProber(ASTNodeProber nodeProber); + + /** + * Gets a prober that applies all added {@link ASTNodeProber}s. + */ + ASTNodeProber getCombinedNodeProber(); +} diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/ExecutionEvents.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/ExecutionEvents.java Mon Apr 28 11:18:15 2014 +0200 @@ -0,0 +1,179 @@ +/* + * Copyright (c) 2013, 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * 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.truffle.api.instrument; + +import com.oracle.truffle.api.frame.*; +import com.oracle.truffle.api.nodes.*; + +/** + * Normal events during program execution at Truffle AST nodes that are reported via a {@link Probe} + * associated with the node, and made available to the probe's attached {@link Instrument}s. + *

+ * Disclaimer: experimental interface under development. + */ +public interface ExecutionEvents { + + /** + * Notifies that an AST node's execute method has just been entered. Callers should assure that + * a matching call to {@link #leave(Node, VirtualFrame, Object)} always follows. + * + * @param astNode The AST node on which the execute method is being called + * @param frame The frame being passed to the execute method + */ + void enter(Node astNode, VirtualFrame frame); + + /** + * Notifies that an AST Node's void-valued execute method is about to exit. + *

+ * Callers should assure (via {@code try/finally}) that a matching call to this method always + * follows a call to {@link #enter(Node, VirtualFrame)}. + * + * @param astNode The AST node on which the execute method is being called + * @param frame The frame that was passed to the execute method + */ + void leave(Node astNode, VirtualFrame frame); + + /** + * Notifies that an AST Node's boolean-valued execute method is about to exit. + *

+ * Callers should assure (via {@code try/finally}) that a matching call to this method always + * follows a call to {@link #enter(Node, VirtualFrame)}. + * + * @param astNode The AST node on which the execute method is being called + * @param frame The frame that was passed to the execute method + * @param result The result of the call to the execute method. + */ + void leave(Node astNode, VirtualFrame frame, boolean result); + + /** + * Notifies that an AST Node's byte-valued execute method is about to exit. + *

+ * Callers should assure (via {@code try/finally}) that a matching call to this method always + * follows a call to {@link #enter(Node, VirtualFrame)}. + * + * @param astNode The AST node on which the execute method is being called + * @param frame The frame that was passed to the execute method + * @param result The result of the call to the execute method. + */ + void leave(Node astNode, VirtualFrame frame, byte result); + + /** + * Notifies that an AST Node's short-valued execute method is about to exit. + *

+ * Callers should assure (via {@code try/finally}) that a matching call to this method always + * follows a call to {@link #enter(Node, VirtualFrame)}. + * + * @param astNode The AST node on which the execute method is being called + * @param frame The frame that was passed to the execute method + * @param result The result of the call to the execute method. + */ + void leave(Node astNode, VirtualFrame frame, short result); + + /** + * Notifies that an AST Node's integer-valued execute method is about to exit. + *

+ * Callers should assure (via {@code try/finally}) that a matching call to this method always + * follows a call to {@link #enter(Node, VirtualFrame)}. + * + * @param astNode The AST node on which the execute method is being called + * @param frame The frame that was passed to the execute method + * @param result The result of the call to the execute method. + */ + void leave(Node astNode, VirtualFrame frame, int result); + + /** + * Notifies that an AST Node's long-valued execute method is about to exit. + *

+ * Callers should assure (via {@code try/finally}) that a matching call to this method always + * follows a call to {@link #enter(Node, VirtualFrame)}. + * + * @param astNode The AST node on which the execute method is being called + * @param frame The frame that was passed to the execute method + * @param result The result of the call to the execute method. + */ + void leave(Node astNode, VirtualFrame frame, long result); + + /** + * Notifies that an AST Node's float-valued execute method is about to exit. + *

+ * Callers should assure (via {@code try/finally}) that a matching call to this method always + * follows a call to {@link #enter(Node, VirtualFrame)}. + * + * @param astNode The AST node on which the execute method is being called + * @param frame The frame that was passed to the execute method + * @param result The result of the call to the execute method. + */ + void leave(Node astNode, VirtualFrame frame, float result); + + /** + * Notifies that an AST Node's double-valued execute method is about to exit. + *

+ * Callers should assure (via {@code try/finally}) that a matching call to this method always + * follows a call to {@link #enter(Node, VirtualFrame)}. + * + * @param astNode The AST node on which the execute method is being called + * @param frame The frame that was passed to the execute method + * @param result The result of the call to the execute method. + */ + void leave(Node astNode, VirtualFrame frame, double result); + + /** + * Notifies that an AST Node's char-valued execute method is about to exit. + *

+ * Callers should assure (via {@code try/finally}) that a matching call to this method always + * follows a call to {@link #enter(Node, VirtualFrame)}. + * + * @param astNode The AST node on which the execute method is being called + * @param frame The frame that was passed to the execute method + * @param result The result of the call to the execute method. + */ + void leave(Node astNode, VirtualFrame frame, char result); + + /** + * Notifies that an AST Node's object-valued execute method is about to exit. + *

+ * Callers should assure (via {@code try/finally}) that a matching call to this method always + * follows a call to {@link #enter(Node, VirtualFrame)}. + * + * @param astNode The AST node on which the execute method is being called + * @param frame The frame that was passed to the execute method + * @param result The result of the call to the execute method. + */ + void leave(Node astNode, VirtualFrame frame, Object result); + + /** + * Notifies that an AST Node's execute method is about to leave under exceptional conditions, + * returning no value. + *

+ * Callers should assure (via {@code try/finally}) that a matching call to this method always + * follows a call to {@link #enter(Node, VirtualFrame)}. + * + * @param astNode The AST node on which the execute method is being called + * @param frame The frame that was passed to the execute method + * @param e the exception associated with the unusual return + */ + void leaveExceptional(Node astNode, VirtualFrame frame, Exception e); + +} diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/Instrument.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/Instrument.java Mon Apr 28 11:18:15 2014 +0200 @@ -0,0 +1,40 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * 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.truffle.api.instrument; + +/** + * A receiver of Truffle AST {@link ExecutionEvents}, propagated from a {@link Probe} to which the + * instrument is attached. + *

+ * Disclaimer: experimental interface under development. + */ +public interface Instrument extends ExecutionEvents { + + /** + * @return the {@link Probe} to which this instrument is attached. + */ + Probe getProbe(); + +} diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/InstrumentEventListener.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/InstrumentEventListener.java Mon Apr 28 11:18:15 2014 +0200 @@ -0,0 +1,67 @@ +/* + * Copyright (c) 2013, 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * 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.truffle.api.instrument; + +import com.oracle.truffle.api.*; +import com.oracle.truffle.api.frame.*; +import com.oracle.truffle.api.nodes.*; + +/** + * A client of the instrumentation framework that requests event notifications from the language + * engine. + */ +public interface InstrumentEventListener { + + /** + * The guest language runtime is starting to load a source. Care should be taken to ensure that + * under any circumstance there is always a following call to {@link #loadEnding(Source)} with + * the same argument. + */ + void loadStarting(Source source); + + /** + * The guest language runtime has finished loading a source. Care should be taken to ensure that + * under any circumstance there is always a prior call to {@link #loadStarting(Source)} with the + * same argument. + */ + void loadEnding(Source source); + + /** + * A guest language call is about to be executed. + */ + void callEntering(Node astNode, String name); + + /** + * A guest language call has just completed. + */ + void callReturned(Node astNode, String name); + + /** + * An opportunity for instrumentation to interact with Truffle AST execution halted at some + * node. + */ + void haltedAt(Node astNode, MaterializedFrame frame); + +} diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/Instrumentation.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/Instrumentation.java Mon Apr 28 11:18:15 2014 +0200 @@ -0,0 +1,66 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * 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.truffle.api.instrument; + +import java.util.*; + +import com.oracle.truffle.api.*; +import com.oracle.truffle.api.source.*; + +public interface Instrumentation { + + /** + * Adds a new specification for how to instrument ASTs. + */ + void addNodeProber(ASTNodeProber nodeProber); + + /** + * Registers a tool interested in being notified about the insertion of a newly created + * {@link Probe} into a Truffle AST. + */ + void addProbeListener(ProbeListener listener); + + /** + * Return the (possibly newly created) {@link Probe} uniquely associated with a particular + * source code location. A newly created probe carries no tags. + * + * @param eventListener an optional listener for certain instrumentation-related events + * @return a probe uniquely associated with an extent of guest language source code. + */ + Probe getProbe(SourceSection sourceSection, InstrumentEventListener eventListener); + + /** + * Returns all existing probes with specific tag, or all probes if {@code tag = null}; empty + * collection if no probes found. + */ + Collection findProbesTaggedAs(PhylumTag tag); + + /** + * Returns all existing probes with first character on a specified line; empty collection if no + * probes found. + */ + Collection findProbesByLine(SourceLineLocation lineLocation); + +} diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/InstrumentationFactory.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/InstrumentationFactory.java Mon Apr 28 11:18:15 2014 +0200 @@ -0,0 +1,36 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * 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.truffle.api.instrument; + +import com.oracle.truffle.api.*; +import com.oracle.truffle.api.instrument.impl.*; + +public class InstrumentationFactory { + + public static Instrumentation create(ExecutionContext context) { + return new InstrumentationImpl(context); + } + +} diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/KillException.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/KillException.java Mon Apr 28 11:18:15 2014 +0200 @@ -0,0 +1,35 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * 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.truffle.api.instrument; + +import com.oracle.truffle.api.nodes.*; + +/** + * Controls breaking out of an execution context, such as a shell or eval. + */ +public final class KillException extends ControlFlowException { + + private static final long serialVersionUID = 3163641880088766957L; +} diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/PhylumTag.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/PhylumTag.java Mon Apr 28 11:18:15 2014 +0200 @@ -0,0 +1,70 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * 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.truffle.api.instrument; + +/** + * Program element "tags" that define user-visible behavior for debugging and other simple tools. + * These categories (phyla) should correspond to program structures that are meaningful to + * a guest language programmer. + *

+ * An untagged Truffle node should be understood as an artifact of the guest language implementation + * and should not be visible to the user of a guest language programming tool. Nodes may also have + * more than one tag, for example a variable assignment that is also a statement. Finally, the + * assignment of tags to nodes could depending on the use-case of whatever tool is using them. + *

+ * This is a somewhat language-agnostic set of phyla, suitable for conventional imperative + * languages, and is being developed incrementally. + *

+ * The need for alternative sets of tags is likely to arise, perhaps for other families of languages + * (for example for mostly expression-oriented languages) or even for specific languages. + *

+ * These are listed alphabetically so that listing from some collection classes will come out in + * that order. + *

+ * Disclaimer: experimental interface under development. + */ +public enum PhylumTag { + + /** + * Marker for a variable assignment. + */ + ASSIGNMENT, + + /** + * Marker for a call site. + */ + CALL, + + /** + * Marker for a location where a guest language exception is about to be thrown. + */ + THROW, + + /** + * Marker for a location where ordinary "stepping" should halt. + */ + STATEMENT; + +} diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/PhylumTagged.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/PhylumTagged.java Mon Apr 28 11:18:15 2014 +0200 @@ -0,0 +1,47 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * 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.truffle.api.instrument; + +import java.util.*; + +/** + * Information about a guest language program element that can be marked as belonging to 0 or more + * {@linkplain PhylumTag tags}. + *

+ * Disclaimer: experimental interface under development. + */ +public interface PhylumTagged { + + /** + * Is this node tagged as belonging to a particular category of language constructs? + */ + boolean isTaggedAs(PhylumTag tag); + + /** + * In which categories has this node been tagged (empty set if none). + */ + Set getPhylumTags(); + +} diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/Probe.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/Probe.java Mon Apr 28 11:18:15 2014 +0200 @@ -0,0 +1,148 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * 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.truffle.api.instrument; + +import com.oracle.truffle.api.*; +import com.oracle.truffle.api.frame.*; +import com.oracle.truffle.api.nodes.*; + +/** + * A collector of {@link ExecutionEvents} at a specific site (node) in a Truffle AST (generated by a + * {@link Wrapper} inserted into the AST) for the purpose of instrumentation. For probes + * associated with programmer-facing tools, there should be no more than one probe associated with a + * particular piece of source code syntax (i.e. a {@link SourceSection}). + *

+ * Any {@linkplain PhylumTag tags} associated with a particular piece of source code syntax are + * managed by the probe. + *

+ * When ASTs are copied, it is presumed that the probe for a site is shared by all AST nodes + * representing that site. + *

+ * A probe holds zero or more {@link Instrument}s, which can be added and removed dynamically. + * Events reported to a probe are propagated to every attached instrument; the order is undefined. + *

+ * Probe methods must be amenable to Truffle/Graal inlining on the assumption that the collection of + * attached instruments seldom changes. The assumption is invalidated when instruments are added or + * removed, but some instruments may change their internal state in such a way that the assumption + * should also be invalidated. + *

+ * Disclaimer: experimental interface under development. + */ +public interface Probe extends PhylumTagged { + + /** + * The source location with which this probe is (presumably uniquely) associated. + */ + SourceSection getSourceLocation(); + + /** + * Mark this probe as being associated with an AST node in some category useful for debugging + * and other tools. + */ + void tagAs(PhylumTag tag); + + /** + * Adds an instrument to this probe. + */ + void addInstrument(Instrument newInstrument); + + /** + * Removes an instrument from this probe. + */ + void removeInstrument(Instrument oldInstrument); + + /** + * Change stepping mode, which is used in association with nodes tagged as + * {@linkplain PhylumTag#STATEMENT statements}. + */ + void setStepping(boolean stepping); + + /** + * Value of stepping mode, which is used in association with nodes tagged as + * {@linkplain PhylumTag#STATEMENT statements}. + */ + boolean isStepping(); + + /** + * @see ExecutionEvents#enter(Node, VirtualFrame) + */ + void notifyEnter(Node astNode, VirtualFrame frame); + + /** + * @see ExecutionEvents#leave(Node, VirtualFrame) + */ + void notifyLeave(Node astNode, VirtualFrame frame); + + /** + * @see ExecutionEvents#leave(Node, VirtualFrame, boolean) + */ + void notifyLeave(Node astNode, VirtualFrame frame, boolean result); + + /** + * @see ExecutionEvents#leave(Node, VirtualFrame, byte) + */ + void notifyLeave(Node astNode, VirtualFrame frame, byte result); + + /** + * @see ExecutionEvents#leave(Node, VirtualFrame, short) + */ + void notifyLeave(Node astNode, VirtualFrame frame, short result); + + /** + * @see ExecutionEvents#leave(Node, VirtualFrame, int) + */ + void notifyLeave(Node astNode, VirtualFrame frame, int result); + + /** + * @see ExecutionEvents#leave(Node, VirtualFrame, long) + */ + void notifyLeave(Node astNode, VirtualFrame frame, long result); + + /** + * @see ExecutionEvents#leave(Node, VirtualFrame, char) + */ + void notifyLeave(Node astNode, VirtualFrame frame, char result); + + /** + * @see ExecutionEvents#leave(Node, VirtualFrame, float) + */ + void notifyLeave(Node astNode, VirtualFrame frame, float result); + + /** + * @see ExecutionEvents#leave(Node, VirtualFrame, double) + */ + void notifyLeave(Node astNode, VirtualFrame frame, double result); + + /** + * @see ExecutionEvents#leave(Node, VirtualFrame, Object) + */ + void notifyLeave(Node astNode, VirtualFrame frame, Object result); + + /** + * @see ExecutionEvents#leaveExceptional(Node, VirtualFrame, Exception) + */ + void notifyLeaveExceptional(Node astNode, VirtualFrame frame, Exception e); + +} diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/ProbeListener.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/ProbeListener.java Mon Apr 28 11:18:15 2014 +0200 @@ -0,0 +1,46 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * 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.truffle.api.instrument; + +import com.oracle.truffle.api.*; + +/** + * Client for receiving events relate to {@link Probe} management. Does not report AST copying. + */ +public interface ProbeListener { + + /** + * Notifies that a newly created (untagged) {@link Probe} has been inserted into a Truffle AST. + * There will be no notification when an existing {@link Probe} is shared by an AST copy. + */ + void newProbeInserted(SourceSection location, Probe probe); + + /** + * Notifies that a (fully constructed) {@link Probe} has been tagged. A subsequent marking with + * the same tag is idempotent and generates no notification. + */ + void probeTaggedAs(Probe probe, PhylumTag tag); + +} diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/QuitException.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/QuitException.java Mon Apr 28 11:18:15 2014 +0200 @@ -0,0 +1,35 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * 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.truffle.api.instrument; + +import com.oracle.truffle.api.nodes.*; + +/** + * Controls breaking out of all executions and ending Truffle execution. + */ +public final class QuitException extends ControlFlowException { + + private static final long serialVersionUID = -4301115629772778413L; +} diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/Visualizer.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/Visualizer.java Mon Apr 28 11:18:15 2014 +0200 @@ -0,0 +1,50 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * 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.truffle.api.instrument; + +import com.oracle.truffle.api.frame.*; + +/** + * Visualization services for guest language and Truffle information. + */ +public interface Visualizer { + + /** + * Gets a printer for Truffle ASTs, possibly specialized to be helpful for a specific guest + * language implementation. + */ + ASTPrinter getASTPrinter(); + + /** + * Converts a value in the guest language to a display string. + */ + String displayValue(Object value); + + /** + * Converts a slot identifier in the guest language to a display string. + */ + String displayIdentifier(FrameSlot slot); + +} diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/Wrapper.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/Wrapper.java Mon Apr 28 11:18:15 2014 +0200 @@ -0,0 +1,57 @@ +/* + * Copyright (c) 2013, 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * 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.truffle.api.instrument; + +import com.oracle.truffle.api.nodes.*; + +/** + * A node that can be inserted into a Truffle AST in order to attach instrumentation at a + * particular node. + *

+ * A wrapper decorates an AST node (its child) by acting as a transparent + * proxy for the child with respect to Truffle execution semantics. + *

+ * A wrapper is also expected to notify its associated {@link Probe} when certain + * {@link ExecutionEvents} occur at the wrapper during program execution. + *

+ * The wrapper's {@link Probe} is shared by every copy of the wrapper made when the AST is copied. + *

+ * Wrappers methods must be amenable to Truffle/Graal inlining. + *

+ * Disclaimer: experimental interface under development. + */ +public interface Wrapper extends PhylumTagged { + + /** + * Gets the AST node being instrumented, which should never be an instance of {@link Wrapper}. + */ + Node getChild(); + + /** + * Gets the {@link Probe} to which events occurring at this wrapper's child are propagated. + */ + Probe getProbe(); + +} diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/impl/DefaultASTPrinter.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/impl/DefaultASTPrinter.java Mon Apr 28 11:18:15 2014 +0200 @@ -0,0 +1,168 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * 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.truffle.api.instrument.impl; + +import java.io.*; +import java.util.*; + +import com.oracle.truffle.api.*; +import com.oracle.truffle.api.instrument.*; +import com.oracle.truffle.api.nodes.*; +import com.oracle.truffle.api.nodes.NodeUtil.NodeClass; +import com.oracle.truffle.api.nodes.NodeUtil.NodeField; +import com.oracle.truffle.api.nodes.NodeUtil.NodeFieldKind; + +/** + * A language-agnostic for printing out various pieces of a Truffle AST. + */ +public class DefaultASTPrinter implements ASTPrinter { + + public DefaultASTPrinter() { + } + + public void printTree(PrintWriter p, Node node, int maxDepth, Node markNode) { + printTree(p, node, maxDepth, markNode, 1); + p.println(); + p.flush(); + } + + public String printTreeToString(Node node, int maxDepth, Node markNode) { + StringWriter out = new StringWriter(); + printTree(new PrintWriter(out), node, maxDepth, markNode); + return out.toString(); + } + + public String printTreeToString(Node node, int maxDepth) { + return printTreeToString(node, maxDepth, null); + } + + private static void printTree(PrintWriter p, Node node, int maxDepth, Node markNode, int level) { + if (node == null) { + p.print("null"); + return; + } + + p.print(nodeName(node)); + + String sep = ""; + p.print("("); + + final SourceSection src = node.getSourceSection(); + if (src != null) { + if (!(src instanceof NullSourceSection)) { + p.print(src.getSource().getName() + ":" + src.getStartLine()); + } + } + if (node instanceof PhylumTagged) { + final PhylumTagged taggedNode = (PhylumTagged) node; + String prefix = ""; + for (PhylumTag tag : taggedNode.getPhylumTags()) { + p.print(prefix); + prefix = ","; + p.print(tag.toString()); + } + + } + + ArrayList childFields = new ArrayList<>(); + + for (NodeField field : NodeClass.get(node.getClass()).getFields()) { + if (field.getKind() == NodeFieldKind.CHILD || field.getKind() == NodeFieldKind.CHILDREN) { + childFields.add(field); + } else if (field.getKind() == NodeFieldKind.DATA) { + // p.print(sep); + // sep = ", "; + // + // final String fieldName = field.getName(); + // switch (fieldName) { + // + // } + // p.print(fieldName); + // p.print(" = "); + // p.print(field.loadValue(node)); + } + } + p.print(")"); + + if (level <= maxDepth) { + + if (childFields.size() != 0) { + p.print(" {"); + for (NodeField field : childFields) { + + Object value = field.loadValue(node); + if (value == null) { + printNewLine(p, level); + p.print(field.getName()); + p.print(" = null "); + } else if (field.getKind() == NodeFieldKind.CHILD) { + final Node valueNode = (Node) value; + printNewLine(p, level, valueNode == markNode); + p.print(field.getName()); + p.print(" = "); + printTree(p, valueNode, maxDepth, markNode, level + 1); + } else if (field.getKind() == NodeFieldKind.CHILDREN) { + printNewLine(p, level); + p.print(field.getName()); + Node[] children = (Node[]) value; + p.print(" = ["); + sep = ""; + for (Node child : children) { + p.print(sep); + sep = ", "; + printTree(p, child, maxDepth, markNode, level + 1); + } + p.print("]"); + } else { + printNewLine(p, level); + p.print(field.getName()); + } + } + printNewLine(p, level - 1); + p.print("}"); + } + } + } + + private static void printNewLine(PrintWriter p, int level, boolean mark) { + p.println(); + for (int i = 0; i < level; i++) { + if (mark && i == 0) { + p.print(" -->"); + } else { + p.print(" "); + } + } + } + + private static void printNewLine(PrintWriter p, int level) { + printNewLine(p, level, false); + } + + private static String nodeName(Node node) { + return node.getClass().getSimpleName(); + } + +} diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/impl/DefaultInstrument.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/impl/DefaultInstrument.java Mon Apr 28 11:18:15 2014 +0200 @@ -0,0 +1,84 @@ +/* + * Copyright (c) 2013, 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * 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.truffle.api.instrument.impl; + +import com.oracle.truffle.api.frame.*; +import com.oracle.truffle.api.instrument.*; +import com.oracle.truffle.api.nodes.*; + +/** + * An {@link Instrument} that implements all {@link ExecutionEvents} notifications with empty + * methods. + */ +public class DefaultInstrument extends InstrumentationNodeImpl implements Instrument { + + protected DefaultInstrument() { + } + + public void enter(Node astNode, VirtualFrame frame) { + } + + public void leave(Node astNode, VirtualFrame frame) { + } + + public void leave(Node astNode, VirtualFrame frame, boolean result) { + leave(astNode, frame, (Object) result); + } + + public void leave(Node astNode, VirtualFrame frame, byte result) { + leave(astNode, frame, (Object) result); + } + + public void leave(Node astNode, VirtualFrame frame, short result) { + leave(astNode, frame, (Object) result); + } + + public void leave(Node astNode, VirtualFrame frame, int result) { + leave(astNode, frame, (Object) result); + } + + public void leave(Node astNode, VirtualFrame frame, long result) { + leave(astNode, frame, (Object) result); + } + + public void leave(Node astNode, VirtualFrame frame, char result) { + leave(astNode, frame, (Object) result); + } + + public void leave(Node astNode, VirtualFrame frame, float result) { + leave(astNode, frame, (Object) result); + } + + public void leave(Node astNode, VirtualFrame frame, double result) { + leave(astNode, frame, (Object) result); + } + + public void leave(Node astNode, VirtualFrame frame, Object result) { + } + + public void leaveExceptional(Node astNode, VirtualFrame frame, Exception e) { + } + +} diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/impl/DefaultVisualizer.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/impl/DefaultVisualizer.java Mon Apr 28 11:18:15 2014 +0200 @@ -0,0 +1,50 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * 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.truffle.api.instrument.impl; + +import com.oracle.truffle.api.frame.*; +import com.oracle.truffle.api.instrument.*; + +public class DefaultVisualizer implements Visualizer { + + private final ASTPrinter astPrinter; + + public DefaultVisualizer() { + this.astPrinter = new DefaultASTPrinter(); + } + + public ASTPrinter getASTPrinter() { + return astPrinter; + } + + public String displayValue(Object value) { + return value.toString(); + } + + public String displayIdentifier(FrameSlot slot) { + return slot.getIdentifier().toString(); + } + +} diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/impl/InstrumentationImpl.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/impl/InstrumentationImpl.java Mon Apr 28 11:18:15 2014 +0200 @@ -0,0 +1,145 @@ +/* + * Copyright (c) 2013, 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * 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.truffle.api.instrument.impl; + +import java.util.*; + +import com.oracle.truffle.api.*; +import com.oracle.truffle.api.instrument.*; +import com.oracle.truffle.api.source.*; + +/** + * @author mlvdv + * + */ +public final class InstrumentationImpl implements Instrumentation { + + private final ExecutionContext context; + + // TODO (mlvdv) maps should really use weak references. + + /** + * Map: SourceSection ==> probe associated with that source section in an AST. + */ + private final Map srcToProbe = new HashMap<>(); + + /** + * Map: Source line ==> probes associated with source sections starting on the line. + */ + private final Map> lineToProbes = new HashMap<>(); + + private final List probeListeners = new ArrayList<>(); + + public InstrumentationImpl(ExecutionContext context) { + this.context = context; + } + + public void addNodeProber(ASTNodeProber nodeProber) { + context.addNodeProber(nodeProber); + } + + public void addProbeListener(ProbeListener listener) { + assert listener != null; + probeListeners.add(listener); + } + + /** + * Return the (possibly newly created) {@link Probe} uniquely associated with a particular + * source code location. A newly created probe carries no tags. + * + * @param eventListener an optional listener for certain instrumentation-related events + * @return a probe uniquely associated with an extent of guest language source code. + */ + public Probe getProbe(SourceSection sourceSection, InstrumentEventListener eventListener) { + assert sourceSection != null; + + Probe probe = srcToProbe.get(sourceSection); + + if (probe != null) { + return probe; + } + probe = InstrumentationNodeImpl.createProbe(this, sourceSection, eventListener); + + // Register new probe by unique SourceSection + srcToProbe.put(sourceSection, probe); + + // Register new probe by source line, there may be more than one + // Create line location for map key + final SourceLineLocation lineLocation = new SourceLineLocation(sourceSection.getSource(), sourceSection.getStartLine()); + + Collection probes = lineToProbes.get(lineLocation); + if (probes == null) { + probes = new ArrayList<>(2); + lineToProbes.put(lineLocation, probes); + } + probes.add(probe); + + for (ProbeListener listener : probeListeners) { + listener.newProbeInserted(sourceSection, probe); + } + + return probe; + } + + /** + * Returns all existing probes with specific tag, or all probes if {@code tag = null}; empty + * collection if no probes found. + */ + public Collection findProbesTaggedAs(PhylumTag tag) { + if (tag == null) { + return new ArrayList<>(srcToProbe.values()); + } + final List probes = new ArrayList<>(); + for (Probe probe : srcToProbe.values()) { + if (probe.isTaggedAs(tag)) { + probes.add(probe); + } + } + return probes; + } + + /** + * Returns all existing probes with first character on a specified line; empty collection if no + * probes found. + */ + public Collection findProbesByLine(SourceLineLocation lineLocation) { + final Collection probes = lineToProbes.get(lineLocation); + if (probes == null) { + return Collections.emptyList(); + } + return new ArrayList<>(probes); + } + + /** + * Receives (from the {@link Probe} implementation) and distributes notification that a + * {@link Probe} has acquired a new {@linkplain PhylumTag tag}. + */ + void newTagAdded(Probe probe, PhylumTag tag) { + for (ProbeListener listener : probeListeners) { + listener.probeTaggedAs(probe, tag); + } + } + +} diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/impl/InstrumentationNodeImpl.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/impl/InstrumentationNodeImpl.java Mon Apr 28 11:18:15 2014 +0200 @@ -0,0 +1,448 @@ +/* + * Copyright (c) 2013, 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * 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.truffle.api.instrument.impl; + +import java.util.*; + +import com.oracle.truffle.api.*; +import com.oracle.truffle.api.frame.*; +import com.oracle.truffle.api.instrument.*; +import com.oracle.truffle.api.nodes.*; + +/** + * Abstract implementation of Truffle {@link Node} to be used for AST probes and instruments. + *

+ * Coordinates propagation of Truffle AST {@link ExecutionEvents}. + */ +public abstract class InstrumentationNodeImpl extends Node implements ExecutionEvents { + + // TODO (mlvdv) This is a pretty awkward design. + + /** + * Creates a new {@link Probe}, presumed to be unique to a particular {@linkplain SourceSection} + * extent of guest language source code. + * + * @param eventListener an optional listener for certain instrumentation-related events. + * @return a new probe + */ + static Probe createProbe(InstrumentationImpl instrumentation, SourceSection sourceSection, InstrumentEventListener eventListener) { + return new ProbeImpl(instrumentation, sourceSection, eventListener); + } + + /** + * Next in chain. + */ + @Child protected InstrumentationNodeImpl next; + + protected InstrumentationNodeImpl() { + } + + /** + * @return the instance of {@link Probe} to which this instrument is attached. + */ + public Probe getProbe() { + final InstrumentationNodeImpl parent = (InstrumentationNodeImpl) getParent(); + return parent == null ? null : parent.getProbe(); + } + + /** + * Add a probe to the end of this probe chain. + */ + void internalAddInstrument(InstrumentationNodeImpl newInstrument) { + if (next == null) { + this.next = insert(newInstrument); + } else { + next.internalAddInstrument(newInstrument); + } + } + + void internalRemoveInstrument(InstrumentationNodeImpl oldInstrument) { + if (next == null) { + throw new RuntimeException("Couldn't find probe to remove: " + oldInstrument); + } else if (next == oldInstrument) { + if (oldInstrument.next == null) { + this.next = null; + } else { + this.next = insert(oldInstrument.next); + oldInstrument.next = null; + } + } else { + next.internalRemoveInstrument(oldInstrument); + } + } + + /** + * Reports to the instance of {@link Probe} holding this instrument that some essential state + * has changed that requires deoptimization. + */ + @CompilerDirectives.SlowPath + protected void notifyProbeChanged(InstrumentationNodeImpl instrument) { + final ProbeImpl probe = (ProbeImpl) getProbe(); + probe.notifyProbeChanged(instrument); + } + + private void internalEnter(Node astNode, VirtualFrame frame) { + enter(astNode, frame); + if (next != null) { + next.internalEnter(astNode, frame); + } + } + + private void internalLeave(Node astNode, VirtualFrame frame) { + leave(astNode, frame); + if (next != null) { + next.internalLeave(astNode, frame); + } + } + + private void internalLeave(Node astNode, VirtualFrame frame, boolean result) { + leave(astNode, frame, result); + if (next != null) { + next.internalLeave(astNode, frame, result); + } + } + + private void internalLeave(Node astNode, VirtualFrame frame, byte result) { + leave(astNode, frame, result); + if (next != null) { + next.internalLeave(astNode, frame, result); + } + } + + private void internalLeave(Node astNode, VirtualFrame frame, short result) { + leave(astNode, frame, result); + if (next != null) { + next.internalLeave(astNode, frame, result); + } + } + + private void internalLeave(Node astNode, VirtualFrame frame, int result) { + leave(astNode, frame, result); + if (next != null) { + next.internalLeave(astNode, frame, result); + } + } + + private void internalLeave(Node astNode, VirtualFrame frame, long result) { + leave(astNode, frame, result); + if (next != null) { + next.internalLeave(astNode, frame, result); + } + } + + private void internalLeave(Node astNode, VirtualFrame frame, char result) { + leave(astNode, frame, result); + if (next != null) { + next.internalLeave(astNode, frame, result); + } + } + + private void internalLeave(Node astNode, VirtualFrame frame, float result) { + leave(astNode, frame, result); + if (next != null) { + next.internalLeave(astNode, frame, result); + } + } + + private void internalLeave(Node astNode, VirtualFrame frame, double result) { + leave(astNode, frame, result); + if (next != null) { + next.internalLeave(astNode, frame, result); + } + } + + private void internalLeave(Node astNode, VirtualFrame frame, Object result) { + leave(astNode, frame, result); + if (next != null) { + next.internalLeave(astNode, frame, result); + } + } + + private void internalLeaveExceptional(Node astNode, VirtualFrame frame, Exception e) { + leaveExceptional(astNode, frame, null); + if (next != null) { + next.internalLeaveExceptional(astNode, frame, e); + } + } + + /** + * Holder of a chain of {@linkplain InstrumentationNodeImpl instruments}: manages the + * {@link Assumption} that none of the instruments have changed since last checked. + *

+ * An instance is intended to be shared by every clone of the AST node with which it is + * originally attached, so it holds no parent pointer. + *

+ * May be categorized by one or more {@linkplain PhylumTag tags}, signifying information useful + * for instrumentation about its AST location(s). + */ + private static final class ProbeImpl extends InstrumentationNodeImpl implements Probe { + + final InstrumentationImpl instrumentation; + + final InstrumentEventListener eventListener; + + @CompilerDirectives.CompilationFinal private Assumption probeUnchanged; + + /** + * When in stepping mode, ordinary line breakpoints are ignored, but every entry at a line + * will cause a halt. + */ + @CompilerDirectives.CompilationFinal private boolean stepping; + + /** + * Source information about the AST node to which this instrumentation is attached. + */ + private final SourceSection probedSourceSection; + + private final Set tags = EnumSet.noneOf(PhylumTag.class); + + private ProbeImpl(InstrumentationImpl instrumentation, SourceSection sourceSection, InstrumentEventListener eventListener) { + this.instrumentation = instrumentation; + this.probedSourceSection = sourceSection; + this.eventListener = eventListener == null ? NullInstrumentEventListener.INSTANCE : eventListener; + this.probeUnchanged = Truffle.getRuntime().createAssumption(); + this.next = null; + } + + @Override + public Probe getProbe() { + return this; + } + + @Override + protected void notifyProbeChanged(InstrumentationNodeImpl instrument) { + probeUnchanged.invalidate(); + probeUnchanged = Truffle.getRuntime().createAssumption(); + } + + public SourceSection getSourceLocation() { + return probedSourceSection; + } + + public void tagAs(PhylumTag tag) { + assert tag != null; + if (!tags.contains(tag)) { + tags.add(tag); + instrumentation.newTagAdded(this, tag); + } + } + + public boolean isTaggedAs(PhylumTag tag) { + assert tag != null; + return tags.contains(tag); + } + + public Set getPhylumTags() { + return tags; + } + + public void setStepping(boolean stepping) { + if (this.stepping != stepping) { + this.stepping = stepping; + probeUnchanged.invalidate(); + probeUnchanged = Truffle.getRuntime().createAssumption(); + } + } + + public boolean isStepping() { + return stepping; + } + + @CompilerDirectives.SlowPath + public void addInstrument(Instrument instrument) { + probeUnchanged.invalidate(); + final InstrumentationNodeImpl instrumentImpl = (InstrumentationNodeImpl) instrument; + super.internalAddInstrument(instrumentImpl); + probeUnchanged = Truffle.getRuntime().createAssumption(); + } + + @CompilerDirectives.SlowPath + public void removeInstrument(Instrument instrument) { + probeUnchanged.invalidate(); + final InstrumentationNodeImpl instrumentImpl = (InstrumentationNodeImpl) instrument; + super.internalRemoveInstrument(instrumentImpl); + probeUnchanged = Truffle.getRuntime().createAssumption(); + } + + public void notifyEnter(Node astNode, VirtualFrame frame) { + if (stepping || next != null) { + if (!probeUnchanged.isValid()) { + CompilerDirectives.transferToInterpreter(); + } + if (stepping) { + eventListener.haltedAt(astNode, frame.materialize()); + } + if (next != null) { + next.internalEnter(astNode, frame); + } + } + } + + public void notifyLeave(Node astNode, VirtualFrame frame) { + if (next != null) { + if (!probeUnchanged.isValid()) { + CompilerDirectives.transferToInterpreter(); + } + next.internalLeave(astNode, frame); + } + } + + public void notifyLeave(Node astNode, VirtualFrame frame, boolean result) { + if (next != null) { + if (!probeUnchanged.isValid()) { + CompilerDirectives.transferToInterpreter(); + } + next.internalLeave(astNode, frame, result); + } + } + + public void notifyLeave(Node astNode, VirtualFrame frame, byte result) { + if (next != null) { + if (!probeUnchanged.isValid()) { + CompilerDirectives.transferToInterpreter(); + } + next.internalLeave(astNode, frame, result); + } + } + + public void notifyLeave(Node astNode, VirtualFrame frame, short result) { + if (next != null) { + if (!probeUnchanged.isValid()) { + CompilerDirectives.transferToInterpreter(); + } + next.internalLeave(astNode, frame, result); + } + } + + public void notifyLeave(Node astNode, VirtualFrame frame, int result) { + if (next != null) { + if (!probeUnchanged.isValid()) { + CompilerDirectives.transferToInterpreter(); + } + next.internalLeave(astNode, frame, result); + } + } + + public void notifyLeave(Node astNode, VirtualFrame frame, long result) { + if (next != null) { + if (!probeUnchanged.isValid()) { + CompilerDirectives.transferToInterpreter(); + } + next.internalLeave(astNode, frame, result); + } + } + + public void notifyLeave(Node astNode, VirtualFrame frame, char result) { + if (next != null) { + if (!probeUnchanged.isValid()) { + CompilerDirectives.transferToInterpreter(); + } + next.internalLeave(astNode, frame, result); + } + } + + public void notifyLeave(Node astNode, VirtualFrame frame, float result) { + if (next != null) { + if (!probeUnchanged.isValid()) { + CompilerDirectives.transferToInterpreter(); + } + next.internalLeave(astNode, frame, result); + } + } + + public void notifyLeave(Node astNode, VirtualFrame frame, double result) { + if (next != null) { + if (!probeUnchanged.isValid()) { + CompilerDirectives.transferToInterpreter(); + } + next.internalLeave(astNode, frame, result); + } + } + + public void notifyLeave(Node astNode, VirtualFrame frame, Object result) { + if (next != null) { + if (!probeUnchanged.isValid()) { + CompilerDirectives.transferToInterpreter(); + } + next.internalLeave(astNode, frame, result); + } + } + + public void notifyLeaveExceptional(Node astNode, VirtualFrame frame, Exception e) { + if (next != null) { + if (!probeUnchanged.isValid()) { + CompilerDirectives.transferToInterpreter(); + } + next.internalLeaveExceptional(astNode, frame, e); + } + } + + public void enter(Node astNode, VirtualFrame frame) { + } + + public void leave(Node astNode, VirtualFrame frame) { + } + + public void leave(Node astNode, VirtualFrame frame, boolean result) { + leave(astNode, frame, (Object) result); + } + + public void leave(Node astNode, VirtualFrame frame, byte result) { + leave(astNode, frame, (Object) result); + } + + public void leave(Node astNode, VirtualFrame frame, short result) { + leave(astNode, frame, (Object) result); + } + + public void leave(Node astNode, VirtualFrame frame, int result) { + leave(astNode, frame, (Object) result); + } + + public void leave(Node astNode, VirtualFrame frame, long result) { + leave(astNode, frame, (Object) result); + } + + public void leave(Node astNode, VirtualFrame frame, char result) { + leave(astNode, frame, (Object) result); + } + + public void leave(Node astNode, VirtualFrame frame, float result) { + leave(astNode, frame, (Object) result); + } + + public void leave(Node astNode, VirtualFrame frame, double result) { + leave(astNode, frame, (Object) result); + } + + public void leave(Node astNode, VirtualFrame frame, Object result) { + } + + public void leaveExceptional(Node astNode, VirtualFrame frame, Exception e) { + } + + } + +} diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/impl/NullInstrumentEventListener.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/impl/NullInstrumentEventListener.java Mon Apr 28 11:18:15 2014 +0200 @@ -0,0 +1,57 @@ +/* + * Copyright (c) 2013, 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * 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.truffle.api.instrument.impl; + +import com.oracle.truffle.api.*; +import com.oracle.truffle.api.frame.*; +import com.oracle.truffle.api.instrument.*; +import com.oracle.truffle.api.nodes.*; + +/** + * Minimal, mostly no-op implementation of instrumentation services. + */ +public final class NullInstrumentEventListener implements InstrumentEventListener { + + public static final InstrumentEventListener INSTANCE = new NullInstrumentEventListener(); + + private NullInstrumentEventListener() { + } + + public void callEntering(Node astNode, String name) { + } + + public void callReturned(Node astNode, String name) { + } + + public void haltedAt(Node astNode, MaterializedFrame frame) { + } + + public void loadStarting(Source source) { + } + + public void loadEnding(Source source) { + } + +} diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/CallNode.java --- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/CallNode.java Fri Apr 25 16:21:07 2014 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,156 +0,0 @@ -/* - * 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. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * 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.truffle.api.nodes; - -import com.oracle.truffle.api.*; -import com.oracle.truffle.api.frame.*; - -/** - * Represents a call to a {@link CallTarget} in the Truffle AST. In addition to calling the - * {@link CallTarget}, this {@link Node} enables the runtime system to implement further - * optimizations. Optimizations that can possibly be applied to a {@link CallNode} are inlining and - * splitting. Inlining inlines this call site into the call graph of the parent {@link CallTarget}. - * Splitting duplicates the {@link CallTarget} using {@link RootNode#split()} to collect call site - * sensitive profiling information. - * - * Please note: This class is not intended to be subclassed by guest language implementations. - * - * @see TruffleRuntime#createCallNode(CallTarget) - * @see #inline() - * @see #split() - */ -public abstract class CallNode extends Node { - - protected final CallTarget callTarget; - - protected CallNode(CallTarget callTarget) { - this.callTarget = callTarget; - } - - /** - * Calls the inner {@link CallTarget} returned by {@link #getCurrentCallTarget()}. - * - * @param arguments the arguments that should be passed to the callee - * @return the return result of the call - */ - public abstract Object call(VirtualFrame frame, Object[] arguments); - - /** - * Returns the originally supplied {@link CallTarget} when this call node was created. Please - * note that the returned {@link CallTarget} is not necessarily the {@link CallTarget} that is - * called. For that use {@link #getCurrentCallTarget()} instead. - * - * @return the {@link CallTarget} provided. - */ - public CallTarget getCallTarget() { - return callTarget; - } - - /** - * Returns true if the underlying runtime system supports inlining for the - * {@link CallTarget} in this {@link CallNode}. - * - * @return true if inlining is supported. - */ - public abstract boolean isInlinable(); - - /** - * Returns true if the {@link CallTarget} in this {@link CallNode} is inlined. A - * {@link CallNode} can either be inlined manually by invoking {@link #inline()} or by the - * runtime system which may at any point decide to inline. - * - * @return true if this method was inlined else false. - */ - public abstract boolean isInlined(); - - /** - * Enforces the runtime system to inline the {@link CallTarget} at this call site. If the - * runtime system does not support inlining or it is already inlined this method has no effect. - */ - public abstract void inline(); - - /** - * Returns true if this {@link CallNode} can be split. A {@link CallNode} can only - * be split if the runtime system supports splitting and if the {@link RootNode} contained the - * {@link CallTarget} returns true for {@link RootNode#isSplittable()}. - * - * @return true if the target can be split - */ - public abstract boolean isSplittable(); - - /** - * Enforces the runtime system to split the {@link CallTarget}. If the {@link CallNode} is not - * splittable this methods has no effect. - */ - public abstract boolean split(); - - /** - * Returns true if the target of the {@link CallNode} was split. - * - * @return if the target was split - */ - public final boolean isSplit() { - return getSplitCallTarget() != null; - } - - /** - * Returns the split {@link CallTarget} if this method is split. - * - * @return the split {@link CallTarget} - */ - public abstract CallTarget getSplitCallTarget(); - - /** - * Returns the used call target when {@link #call(VirtualFrame, Object[])} is invoked. If the - * {@link CallTarget} was split this method returns the {@link CallTarget} returned by - * {@link #getSplitCallTarget()}. - * - * @return the used {@link CallTarget} when node is called - */ - public CallTarget getCurrentCallTarget() { - CallTarget split = getSplitCallTarget(); - if (split != null) { - return split; - } else { - return getCallTarget(); - } - } - - /** - * Returns the {@link RootNode} associated with {@link CallTarget} returned by - * {@link #getCurrentCallTarget()}. If the stored {@link CallTarget} does not contain a - * {@link RootNode} this method returns null. - * - * @see #getCurrentCallTarget() - * @return the root node of the used call target - */ - public final RootNode getCurrentRootNode() { - CallTarget target = getCurrentCallTarget(); - if (target instanceof RootCallTarget) { - return ((RootCallTarget) target).getRootNode(); - } - return null; - } -} diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/DirectCallNode.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/DirectCallNode.java Mon Apr 28 11:18:15 2014 +0200 @@ -0,0 +1,170 @@ +/* + * 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. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * 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.truffle.api.nodes; + +import com.oracle.truffle.api.*; +import com.oracle.truffle.api.frame.*; + +/** + * Represents a direct call to a {@link CallTarget}. Direct calls are calls for which the + * {@link CallTarget} remains the same for each consecutive call. This part of the Truffle API + * enables the runtime system to perform additional optimizations on direct calls. + * + * Optimizations that can be applied to a {@link DirectCallNode} are inlining and splitting. + * Inlining inlines this call site into the call graph of the parent {@link CallTarget}. Splitting + * duplicates the {@link CallTarget} using {@link RootNode#split()} to collect call site sensitive + * profiling information. + * + * Please note: This class is not intended to be subclassed by guest language implementations. + * + * @see IndirectCallNode for calls with a non-constant target + * @see TruffleRuntime#createDirectCallNode(CallTarget) + * @see #forceInlining() + * @see #split() + */ +public abstract class DirectCallNode extends Node { + + protected final CallTarget callTarget; + + protected DirectCallNode(CallTarget callTarget) { + this.callTarget = callTarget; + } + + /** + * Calls the inner {@link CallTarget} returned by {@link #getCurrentCallTarget()}. + * + * @param arguments the arguments that should be passed to the callee + * @return the return result of the call + */ + public abstract Object call(VirtualFrame frame, Object[] arguments); + + /** + * Returns the originally supplied {@link CallTarget} when this call node was created. Please + * note that the returned {@link CallTarget} is not necessarily the {@link CallTarget} that is + * called. For that use {@link #getCurrentCallTarget()} instead. + * + * @return the {@link CallTarget} provided. + */ + public CallTarget getCallTarget() { + return callTarget; + } + + /** + * Returns true if the underlying runtime system supports inlining for the + * {@link CallTarget} in this {@link DirectCallNode}. + * + * @return true if inlining is supported. + */ + public abstract boolean isInlinable(); + + /** + * Returns true if the {@link CallTarget} is forced to be inlined. A + * {@link DirectCallNode} can either be inlined manually by invoking {@link #forceInlining()} or + * by the runtime system which may at any point decide to inline. + * + * @return true if this method was inlined else false. + */ + public abstract boolean isInliningForced(); + + /** + * Enforces the runtime system to inline the {@link CallTarget} at this call site. If the + * runtime system does not support inlining or it is already inlined this method has no effect. + * The runtime system may decide to not inline calls which were forced to inline. + */ + public abstract void forceInlining(); + + /** + * Returns true if the runtime system has decided to inline this call-site. If the + * {@link DirectCallNode} was forced to inline then this does not necessarily mean that the + * {@link DirectCallNode} is really going to be inlined. This depends on whether or not the + * runtime system supports inlining. The runtime system may also decide to not inline calls + * which were forced to inline. + */ + public abstract boolean isInlined(); + + /** + * Returns true if this {@link DirectCallNode} can be split. A + * {@link DirectCallNode} can only be split if the runtime system supports splitting and if the + * {@link RootNode} contained the {@link CallTarget} returns true for + * {@link RootNode#isSplittable()}. + * + * @return true if the target can be split + */ + public abstract boolean isSplittable(); + + /** + * Enforces the runtime system to split the {@link CallTarget}. If the {@link DirectCallNode} is + * not splittable this methods has no effect. + */ + public abstract boolean split(); + + /** + * Returns true if the target of the {@link DirectCallNode} was split. + * + * @return if the target was split + */ + public final boolean isSplit() { + return getSplitCallTarget() != null; + } + + /** + * Returns the split {@link CallTarget} if this method is split. + * + * @return the split {@link CallTarget} + */ + public abstract CallTarget getSplitCallTarget(); + + /** + * Returns the used call target when {@link #call(VirtualFrame, Object[])} is invoked. If the + * {@link CallTarget} was split this method returns the {@link CallTarget} returned by + * {@link #getSplitCallTarget()}. + * + * @return the used {@link CallTarget} when node is called + */ + public CallTarget getCurrentCallTarget() { + CallTarget split = getSplitCallTarget(); + if (split != null) { + return split; + } else { + return getCallTarget(); + } + } + + /** + * Returns the {@link RootNode} associated with {@link CallTarget} returned by + * {@link #getCurrentCallTarget()}. If the stored {@link CallTarget} does not contain a + * {@link RootNode} this method returns null. + * + * @see #getCurrentCallTarget() + * @return the root node of the used call target + */ + public final RootNode getCurrentRootNode() { + CallTarget target = getCurrentCallTarget(); + if (target instanceof RootCallTarget) { + return ((RootCallTarget) target).getRootNode(); + } + return null; + } +} diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/IndirectCallNode.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/IndirectCallNode.java Mon Apr 28 11:18:15 2014 +0200 @@ -0,0 +1,51 @@ +/* + * 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. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * 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.truffle.api.nodes; + +import com.oracle.truffle.api.*; +import com.oracle.truffle.api.frame.*; + +/** + * Represents an indirect call to a {@link CallTarget}. Indirect calls are calls for which the + * {@link CallTarget} may change dynamically for each consecutive call. This part of the Truffle API + * enables the runtime system to perform additional optimizations on indirect calls. + * + * Please note: This class is not intended to be sub classed by guest language implementations. + * + * @see DirectCallNode for faster calls with a constantly known {@link CallTarget}. + */ +public abstract class IndirectCallNode extends Node { + + /** + * Performs an indirect call to the given {@link CallTarget} target with the provided arguments. + * + * @param frame the caller frame + * @param target the {@link CallTarget} to call + * @param arguments the arguments to provide + * @return the return value of the call + */ + public abstract Object call(VirtualFrame frame, CallTarget target, Object[] arguments); + +} diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/Node.java --- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/Node.java Fri Apr 25 16:21:07 2014 +0200 +++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/Node.java Mon Apr 28 11:18:15 2014 +0200 @@ -191,8 +191,12 @@ if (newChild == this) { throw new IllegalStateException("The parent of a node can never be the node itself."); } + boolean isInserted = newChild.parent == null; newChild.parent = this; newChild.adoptHelper(); + if (isInserted) { + newChild.onAdopt(); + } } private void adoptHelper() { @@ -209,8 +213,12 @@ if (newChild == this) { throw new IllegalStateException("The parent of a node can never be the node itself."); } + boolean isInserted = newChild.parent == null; newChild.parent = this; newChild.adoptUnadoptedHelper(); + if (isInserted) { + newChild.onAdopt(); + } } private void adoptUnadoptedHelper() { @@ -332,7 +340,6 @@ } private void traceRewrite(Node newNode, CharSequence reason) { - if (TruffleOptions.TraceRewritesFilterFromCost != null) { if (filterByKind(this, TruffleOptions.TraceRewritesFilterFromCost)) { return; @@ -352,8 +359,21 @@ return; } + final SourceSection reportedSourceSection = getEncapsulatingSourceSection(); + PrintStream out = System.out; - out.printf("[truffle] rewrite %-50s |From %-40s |To %-40s |Reason %s.%n", this.toString(), formatNodeInfo(this), formatNodeInfo(newNode), reason); + out.printf("[truffle] rewrite %-50s |From %-40s |To %-40s |Reason %s%s%n", this.toString(), formatNodeInfo(this), formatNodeInfo(newNode), reason != null && reason.length() > 0 ? reason + : "unknown", reportedSourceSection != null ? " at " + reportedSourceSection.getShortDescription() : ""); + } + + /** + * Subclasses of {@link Node} can implement this method to execute extra functionality when a + * node is effectively inserted into the AST. The {@code onAdopt} callback is called after the + * node has been effectively inserted, and it is guaranteed to be called only once for any given + * node. + */ + protected void onAdopt() { + // empty default } private static String formatNodeInfo(Node node) { diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/NodeUtil.java --- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/NodeUtil.java Fri Apr 25 16:21:07 2014 +0200 +++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/NodeUtil.java Mon Apr 28 11:18:15 2014 +0200 @@ -636,8 +636,8 @@ nodeCount++; } - if (visitInlinedCallNodes && node instanceof CallNode) { - CallNode call = (CallNode) node; + if (visitInlinedCallNodes && node instanceof DirectCallNode) { + DirectCallNode call = (DirectCallNode) node; if (call.isInlined()) { Node target = ((RootCallTarget) call.getCurrentCallTarget()).getRootNode(); if (target != null) { @@ -763,7 +763,7 @@ /** * Prints a human readable form of a {@link Node} AST to the given {@link PrintStream}. This * print method does not check for cycles in the node structure. - * + * * @param out the stream to print to. * @param node the root node to write */ diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/RootNode.java --- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/RootNode.java Fri Apr 25 16:21:07 2014 +0200 +++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/RootNode.java Mon Apr 28 11:18:15 2014 +0200 @@ -58,7 +58,7 @@ * Creates a split {@link RootNode} based on the current {@link RootNode}. This method should * return an AST that was never executed and must not be shared with other {@link RootNode} or * {@link CallTarget} instances. This method is intended to be overridden by a subclass. - * + * * @return the split {@link RootNode} */ public RootNode split() { @@ -67,10 +67,10 @@ /** * Returns true if this {@link RootNode} can be split. A {@link RootNode} can be - * split inside of a {@link CallTarget} that is invoked using a {@link CallNode}. If this method - * returns true a proper implementation of {@link #split()} must also be provided. - * This method is intended to be overridden by a subclass. - * + * split inside of a {@link CallTarget} that is invoked using a {@link DirectCallNode}. If this + * method returns true a proper implementation of {@link #split()} must also be + * provided. This method is intended to be overridden by a subclass. + * * @return true if splittable else false. */ public boolean isSplittable() { @@ -89,7 +89,7 @@ /** * Executes this function using the specified frame and returns the result value. - * + * * @param frame the frame of the currently executing guest language method * @return the value of the execution */ diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/instrument/DefaultNodeInstrumenter.java --- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/instrument/DefaultNodeInstrumenter.java Fri Apr 25 16:21:07 2014 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,38 +0,0 @@ -/* - * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * 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.truffle.api.nodes.instrument; - -import com.oracle.truffle.api.nodes.*; - -/** - * A no-op node instrumenter; always returns the node unproxied and unmodified. - */ -public class DefaultNodeInstrumenter implements NodeInstrumenter { - - public Node instrumentAs(Node node, NodePhylum phylum, Object... args) { - return node; - } - -} diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/instrument/InstrumentationNode.java --- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/instrument/InstrumentationNode.java Fri Apr 25 16:21:07 2014 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,36 +0,0 @@ -/* - * 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. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * 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.truffle.api.nodes.instrument; - -/** - * Marker interface for all Truffle instrumentation nodes: nodes that are do not - * appear in Truffle ASTs as part of a language's execution semantics. - *

- * In documentation related to instrumentation nodes, these are distinguished by referring to all - * other nodes (i.e. ones that do implement language semantics) as AST nodes. - */ -public interface InstrumentationNode { - -} diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/instrument/InstrumentationProbeEvents.java --- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/instrument/InstrumentationProbeEvents.java Fri Apr 25 16:21:07 2014 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,190 +0,0 @@ -/* - * 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. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * 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.truffle.api.nodes.instrument; - -import com.oracle.truffle.api.frame.*; -import com.oracle.truffle.api.nodes.*; - -/** - * Marker interface for all Truffle instrumentation nodes: nodes that are do not - * appear in Truffle ASTs as part of a language's execution semantics. - *

- * In documentation related to instrumentation nodes, these are distinguished by referring to all - * other nodes (i.e. ones that do implement language semantics) as AST nodes. - */ -public interface InstrumentationProbeEvents { - - /** - * Notifies a probe that receiver that an AST node's execute method has just been entered. - * Callers should assure that a matching call to {@link #leave(Node, VirtualFrame, Object)} - * always follows. - * - * @param astNode The AST node on which the execute method is being called - * @param frame The frame being passed to the execute method - */ - void enter(Node astNode, VirtualFrame frame); - - /** - * Notifies a probe that an AST Node's void-valued execute method is about to exit. - *

- * Callers should assure (via {@code try/finally}) that a matching call to this method always - * follows a call to {@link #enter(Node, VirtualFrame)}. - * - * @param astNode The AST node on which the execute method is being called - * @param frame The frame that was passed to the execute method - */ - void leave(Node astNode, VirtualFrame frame); - - /** - * Notifies a probe that an AST Node's boolean-valued execute method is about to exit. - *

- * Callers should assure (via {@code try/finally}) that a matching call to this method always - * follows a call to {@link #enter(Node, VirtualFrame)}. - * - * @param astNode The AST node on which the execute method is being called - * @param frame The frame that was passed to the execute method - * @param result The result of the call to the execute method. - */ - void leave(Node astNode, VirtualFrame frame, boolean result); - - /** - * Notifies a probe that an AST Node's byte-valued execute method is about to exit. - *

- * Callers should assure (via {@code try/finally}) that a matching call to this method always - * follows a call to {@link #enter(Node, VirtualFrame)}. - * - * @param astNode The AST node on which the execute method is being called - * @param frame The frame that was passed to the execute method - * @param result The result of the call to the execute method. - */ - void leave(Node astNode, VirtualFrame frame, byte result); - - /** - * Notifies a probe that an AST Node's short-valued execute method is about to exit. - *

- * Callers should assure (via {@code try/finally}) that a matching call to this method always - * follows a call to {@link #enter(Node, VirtualFrame)}. - * - * @param astNode The AST node on which the execute method is being called - * @param frame The frame that was passed to the execute method - * @param result The result of the call to the execute method. - */ - void leave(Node astNode, VirtualFrame frame, short result); - - /** - * Notifies a probe that an AST Node's integer-valued execute method is about to exit. - *

- * Callers should assure (via {@code try/finally}) that a matching call to this method always - * follows a call to {@link #enter(Node, VirtualFrame)}. - * - * @param astNode The AST node on which the execute method is being called - * @param frame The frame that was passed to the execute method - * @param result The result of the call to the execute method. - */ - void leave(Node astNode, VirtualFrame frame, int result); - - /** - * Notifies a probe that an AST Node's long-valued execute method is about to exit. - *

- * Callers should assure (via {@code try/finally}) that a matching call to this method always - * follows a call to {@link #enter(Node, VirtualFrame)}. - * - * @param astNode The AST node on which the execute method is being called - * @param frame The frame that was passed to the execute method - * @param result The result of the call to the execute method. - */ - void leave(Node astNode, VirtualFrame frame, long result); - - /** - * Notifies a probe that an AST Node's float-valued execute method is about to exit. - *

- * Callers should assure (via {@code try/finally}) that a matching call to this method always - * follows a call to {@link #enter(Node, VirtualFrame)}. - * - * @param astNode The AST node on which the execute method is being called - * @param frame The frame that was passed to the execute method - * @param result The result of the call to the execute method. - */ - void leave(Node astNode, VirtualFrame frame, float result); - - /** - * Notifies a probe that an AST Node's double-valued execute method is about to exit. - *

- * Callers should assure (via {@code try/finally}) that a matching call to this method always - * follows a call to {@link #enter(Node, VirtualFrame)}. - * - * @param astNode The AST node on which the execute method is being called - * @param frame The frame that was passed to the execute method - * @param result The result of the call to the execute method. - */ - void leave(Node astNode, VirtualFrame frame, double result); - - /** - * Notifies a probe that an AST Node's char-valued execute method is about to exit. - *

- * Callers should assure (via {@code try/finally}) that a matching call to this method always - * follows a call to {@link #enter(Node, VirtualFrame)}. - * - * @param astNode The AST node on which the execute method is being called - * @param frame The frame that was passed to the execute method - * @param result The result of the call to the execute method. - */ - void leave(Node astNode, VirtualFrame frame, char result); - - /** - * Notifies a probe that an AST Node's object-valued execute method is about to exit. - *

- * Callers should assure (via {@code try/finally}) that a matching call to this method always - * follows a call to {@link #enter(Node, VirtualFrame)}. - * - * @param astNode The AST node on which the execute method is being called - * @param frame The frame that was passed to the execute method - * @param result The result of the call to the execute method. - */ - void leave(Node astNode, VirtualFrame frame, Object result); - - /** - * Notifies a probe that an AST Node's execute method is about to leave under exceptional - * conditions, returning no value. - *

- * Callers should assure (via {@code try/finally}) that a matching call to this method always - * follows a call to {@link #enter(Node, VirtualFrame)}. - * - * @param astNode The AST node on which the execute method is being called - * @param frame The frame that was passed to the execute method - * @param e the exception associated with the unusual return - */ - void leaveExceptional(Node astNode, VirtualFrame frame, Exception e); - - /** - * Notifies a probe that an AST node is about to be replaced with another. - * - * @param oldAstNode the AST node currently in the tree - * @param newAstNode the AST replacement node - * @param reason explanation for the replacement - */ - void replace(Node oldAstNode, Node newAstNode, String reason); - -} diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/instrument/InstrumentationProbeNode.java --- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/instrument/InstrumentationProbeNode.java Fri Apr 25 16:21:07 2014 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,500 +0,0 @@ -/* - * Copyright (c) 2013, 2014, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * 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.truffle.api.nodes.instrument; - -import java.util.*; - -import com.oracle.truffle.api.*; -import com.oracle.truffle.api.frame.*; -import com.oracle.truffle.api.nodes.*; - -/** - * A probe: a Truffle instrumentation node that holds code to perform some action - * when notified (via a {@linkplain InstrumentationProxyNode proxy node} in the AST) of a - * {@linkplain InstrumentationProbeEvents probe event} taking place at the AST node. - *

- * Probes are only active when attached to a {@linkplain ProbeChain "probe chain"} that is referred - * to by one or more {@linkplain InstrumentationProxyNode proxy nodes} in an AST. - */ -public abstract class InstrumentationProbeNode extends Node implements InstrumentationNode, InstrumentationProbeEvents { - - /** - * Next in chain. - */ - @Child protected InstrumentationProbeNode next; - - protected InstrumentationProbeNode() { - } - - protected int countProbes() { - return next == null ? 0 : next.countProbes() + 1; - } - - protected boolean isStepping() { - final InstrumentationProbeNode parent = (InstrumentationProbeNode) getParent(); - return parent.isStepping(); - } - - /** - * Add a probe to the end of this probe chain. - */ - protected void internalAppendProbe(InstrumentationProbeNode newProbeNode) { - if (next == null) { - this.next = insert(newProbeNode); - } else { - next.internalAppendProbe(newProbeNode); - } - } - - protected void internalRemoveProbe(InstrumentationProbeNode oldProbeNode) { - if (next == null) { - throw new RuntimeException("Couldn't find probe to remove: " + oldProbeNode); - } else if (next == oldProbeNode) { - if (oldProbeNode.next == null) { - this.next = null; - } else { - this.next = insert(oldProbeNode.next); - oldProbeNode.next = null; - } - } else { - next.internalRemoveProbe(oldProbeNode); - } - } - - /** - * Passes up the chain notification that a probe has changed its execution state in a way that - * invalidates fast path code. Assumes that there is an instance of {@link ProbeChain} at the - * head of the chain. - */ - @CompilerDirectives.SlowPath - protected void notifyProbeChanged(InstrumentationProbeNode probeNode) { - final InstrumentationProbeNode parent = (InstrumentationProbeNode) getParent(); - parent.notifyProbeChanged(probeNode); - } - - // TODO (mlvdv) making the internal*() methods public is a workaround for a bug/limitation in - // the Truffle compiler; they are intended to be private. - - public void internalEnter(Node astNode, VirtualFrame frame) { - enter(astNode, frame); - if (next != null) { - next.internalEnter(astNode, frame); - } - } - - public void internalLeave(Node astNode, VirtualFrame frame) { - leave(astNode, frame); - if (next != null) { - next.internalLeave(astNode, frame); - } - } - - public void internalLeave(Node astNode, VirtualFrame frame, boolean result) { - leave(astNode, frame, result); - if (next != null) { - next.internalLeave(astNode, frame, result); - } - } - - public void internalLeave(Node astNode, VirtualFrame frame, byte result) { - leave(astNode, frame, result); - if (next != null) { - next.internalLeave(astNode, frame, result); - } - } - - public void internalLeave(Node astNode, VirtualFrame frame, short result) { - leave(astNode, frame, result); - if (next != null) { - next.internalLeave(astNode, frame, result); - } - } - - public void internalLeave(Node astNode, VirtualFrame frame, int result) { - leave(astNode, frame, result); - if (next != null) { - next.internalLeave(astNode, frame, result); - } - } - - public void internalLeave(Node astNode, VirtualFrame frame, long result) { - leave(astNode, frame, result); - if (next != null) { - next.internalLeave(astNode, frame, result); - } - } - - public void internalLeave(Node astNode, VirtualFrame frame, char result) { - leave(astNode, frame, result); - if (next != null) { - next.internalLeave(astNode, frame, result); - } - } - - public void internalLeave(Node astNode, VirtualFrame frame, float result) { - leave(astNode, frame, result); - if (next != null) { - next.internalLeave(astNode, frame, result); - } - } - - public void internalLeave(Node astNode, VirtualFrame frame, double result) { - leave(astNode, frame, result); - if (next != null) { - next.internalLeave(astNode, frame, result); - } - } - - public void internalLeave(Node astNode, VirtualFrame frame, Object result) { - leave(astNode, frame, result); - if (next != null) { - next.internalLeave(astNode, frame, result); - } - } - - public void internalLeaveExceptional(Node astNode, VirtualFrame frame, Exception e) { - leaveExceptional(astNode, frame, null); - if (next != null) { - next.internalLeaveExceptional(astNode, frame, e); - } - } - - public void internalReplace(Node oldAstNode, Node newAstNode, String reason) { - replace(oldAstNode, newAstNode, reason); - if (next != null) { - next.internalReplace(oldAstNode, newAstNode, reason); - } - } - - /** - * A probe implementation that implements all of {@link InstrumentationProbeEvents} with empty - * methods; concrete subclasses can override only the methods for which something is to be done. - */ - public static class DefaultProbeNode extends InstrumentationProbeNode { - - private final ExecutionContext executionContext; - - protected DefaultProbeNode(ExecutionContext context) { - this.executionContext = context; - } - - public ExecutionContext getContext() { - return executionContext; - } - - public void enter(Node astNode, VirtualFrame frame) { - } - - public void leave(Node astNode, VirtualFrame frame) { - } - - public void leave(Node astNode, VirtualFrame frame, boolean result) { - leave(astNode, frame, (Object) result); - } - - public void leave(Node astNode, VirtualFrame frame, byte result) { - leave(astNode, frame, (Object) result); - } - - public void leave(Node astNode, VirtualFrame frame, short result) { - leave(astNode, frame, (Object) result); - } - - public void leave(Node astNode, VirtualFrame frame, int result) { - leave(astNode, frame, (Object) result); - } - - public void leave(Node astNode, VirtualFrame frame, long result) { - leave(astNode, frame, (Object) result); - } - - public void leave(Node astNode, VirtualFrame frame, char result) { - leave(astNode, frame, (Object) result); - } - - public void leave(Node astNode, VirtualFrame frame, float result) { - leave(astNode, frame, (Object) result); - } - - public void leave(Node astNode, VirtualFrame frame, double result) { - leave(astNode, frame, (Object) result); - } - - public void leave(Node astNode, VirtualFrame frame, Object result) { - } - - public void leaveExceptional(Node astNode, VirtualFrame frame, Exception e) { - } - - public void replace(Node oldAstNode, Node newAstNode, String reason) { - } - - } - - /** - * Holder of a chain of {@linkplain InstrumentationProbeNode probes}: manages the - * {@link Assumption} that the chain has not changed since checked checked. - *

- * May be categorized by one or more {@linkplain NodePhylum node phyla}, signifying information - * useful for instrumentation about its AST location(s). - */ - public static final class ProbeChain extends DefaultProbeNode implements PhylumMarked { - - @CompilerDirectives.CompilationFinal private Assumption probeUnchanged; - - /** - * When in stepping mode, ordinary line breakpoints are ignored, but every entry at a line - * will cause a halt. - */ - @CompilerDirectives.CompilationFinal private boolean stepping; - - /** - * Source information about the node to which this probe chain is attached; it isn't - * otherwise available. A probe chain is shared by every copy made during runtime, so there - * is no parent pointer. - */ - private final SourceSection probedSourceSection; - - private final Set phyla = EnumSet.noneOf(NodePhylum.class); - - private final String description; // for debugging - - /** - * Creates a new, empty chain of {@linkplain InstrumentationProbeNode probes}, to which - * probes can be added/removed, and all of which will be notified of - * {@linkplain InstrumentationProbeEvents events} when the chain is notified. - */ - public ProbeChain(ExecutionContext context, SourceSection sourceSection, String description) { - super(context); - this.probeUnchanged = Truffle.getRuntime().createAssumption(); - this.probedSourceSection = sourceSection; - this.description = description; - this.next = null; - } - - public int probeCount() { - return countProbes(); - } - - public String getDescription() { - return description; - } - - public SourceSection getProbedSourceSection() { - return probedSourceSection; - } - - /** - * Mark this probe chain as being associated with an AST node in some category useful for - * debugging and other tools. - */ - public void markAs(NodePhylum phylum) { - assert phylum != null; - phyla.add(phylum); - } - - /** - * Is this probe chain as being associated with an AST node in some category useful for - * debugging and other tools. - */ - public boolean isMarkedAs(NodePhylum phylum) { - assert phylum != null; - return phyla.contains(phylum); - } - - /** - * In which categories is the AST (with which this probe is associated) marked? - */ - public Set getPhylumMarks() { - return phyla; - } - - /** - * Change stepping mode for statements. - */ - public void setStepping(boolean stepping) { - if (this.stepping != stepping) { - this.stepping = stepping; - probeUnchanged.invalidate(); - probeUnchanged = Truffle.getRuntime().createAssumption(); - } - } - - @Override - protected boolean isStepping() { - return stepping; - } - - @Override - protected int countProbes() { - // The head of the chain does not itself hold a probe - return next == null ? 0 : next.countProbes(); - } - - @Override - protected void notifyProbeChanged(InstrumentationProbeNode probeNode) { - probeUnchanged.invalidate(); - probeUnchanged = Truffle.getRuntime().createAssumption(); - } - - @CompilerDirectives.SlowPath - public void appendProbe(InstrumentationProbeNode newProbeNode) { - probeUnchanged.invalidate(); - super.internalAppendProbe(newProbeNode); - probeUnchanged = Truffle.getRuntime().createAssumption(); - } - - @CompilerDirectives.SlowPath - public void removeProbe(InstrumentationProbeNode oldProbeNode) { - probeUnchanged.invalidate(); - super.internalRemoveProbe(oldProbeNode); - probeUnchanged = Truffle.getRuntime().createAssumption(); - } - - public void notifyEnter(Node astNode, VirtualFrame frame) { - if (stepping || next != null) { - if (!probeUnchanged.isValid()) { - CompilerDirectives.transferToInterpreter(); - } - if (stepping) { - getContext().getDebugContext().getDebugManager().haltedAt(astNode, frame.materialize()); - } - if (next != null) { - next.internalEnter(astNode, frame); - } - } - } - - public void notifyLeave(Node astNode, VirtualFrame frame) { - if (next != null) { - if (!probeUnchanged.isValid()) { - CompilerDirectives.transferToInterpreter(); - } - next.internalLeave(astNode, frame); - } - } - - public void notifyLeave(Node astNode, VirtualFrame frame, boolean result) { - if (next != null) { - if (!probeUnchanged.isValid()) { - CompilerDirectives.transferToInterpreter(); - } - next.internalLeave(astNode, frame, result); - } - } - - public void notifyLeave(Node astNode, VirtualFrame frame, byte result) { - if (next != null) { - if (!probeUnchanged.isValid()) { - CompilerDirectives.transferToInterpreter(); - } - next.internalLeave(astNode, frame, result); - } - } - - public void notifyLeave(Node astNode, VirtualFrame frame, short result) { - if (next != null) { - if (!probeUnchanged.isValid()) { - CompilerDirectives.transferToInterpreter(); - } - next.internalLeave(astNode, frame, result); - } - } - - public void notifyLeave(Node astNode, VirtualFrame frame, int result) { - if (next != null) { - if (!probeUnchanged.isValid()) { - CompilerDirectives.transferToInterpreter(); - } - next.internalLeave(astNode, frame, result); - } - } - - public void notifyLeave(Node astNode, VirtualFrame frame, long result) { - if (next != null) { - if (!probeUnchanged.isValid()) { - CompilerDirectives.transferToInterpreter(); - } - next.internalLeave(astNode, frame, result); - } - } - - public void notifyLeave(Node astNode, VirtualFrame frame, char result) { - if (next != null) { - if (!probeUnchanged.isValid()) { - CompilerDirectives.transferToInterpreter(); - } - next.internalLeave(astNode, frame, result); - } - } - - public void notifyLeave(Node astNode, VirtualFrame frame, float result) { - if (next != null) { - if (!probeUnchanged.isValid()) { - CompilerDirectives.transferToInterpreter(); - } - next.internalLeave(astNode, frame, result); - } - } - - public void notifyLeave(Node astNode, VirtualFrame frame, double result) { - if (next != null) { - if (!probeUnchanged.isValid()) { - CompilerDirectives.transferToInterpreter(); - } - next.internalLeave(astNode, frame, result); - } - } - - public void notifyLeave(Node astNode, VirtualFrame frame, Object result) { - if (next != null) { - if (!probeUnchanged.isValid()) { - CompilerDirectives.transferToInterpreter(); - } - next.internalLeave(astNode, frame, result); - } - } - - public void notifyLeaveExceptional(Node astNode, VirtualFrame frame, Exception e) { - if (next != null) { - if (!probeUnchanged.isValid()) { - CompilerDirectives.transferToInterpreter(); - } - next.internalLeaveExceptional(astNode, frame, e); - } - } - - public void notifyReplace(Node oldAstNode, Node newAstNode, String reason) { - if (next != null) { - if (!probeUnchanged.isValid()) { - CompilerDirectives.transferToInterpreter(); - } - next.internalReplace(oldAstNode, newAstNode, reason); - } - } - - } - -} diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/instrument/InstrumentationProxyNode.java --- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/instrument/InstrumentationProxyNode.java Fri Apr 25 16:21:07 2014 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,53 +0,0 @@ -/* - * Copyright (c) 2013, 2014, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * 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.truffle.api.nodes.instrument; - -import com.oracle.truffle.api.nodes.*; -import com.oracle.truffle.api.nodes.instrument.InstrumentationProbeNode.ProbeChain; - -/** - * Interface implemented by language-specific Truffle proxy nodes: nodes that do - * not participate in the language's execution semantics, but which are inserted into an AST so that - * tools (e.g. tracers, analyzers, debuggers) can be notified of AST interpretation events and - * possibly intervene. - *

- * Language-specific proxy nodes call notification methods on an attached {@linkplain ProbeChain - * probe chain} which passes along {@linkplain InstrumentationProbeEvents events} to any - * {@linkplain InstrumentationProbeNode probes} that might have been attached. - */ -public interface InstrumentationProxyNode extends InstrumentationNode, PhylumMarked { - - /** - * Gets the non-instrumentation node being proxied. - */ - Node getChild(); - - /** - * Gets the chain of probes to which events at this node are delegated. Note that a chain of - * probes may be used by more than one proxy. - */ - ProbeChain getProbeChain(); - -} diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/instrument/NodeInstrumenter.java --- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/instrument/NodeInstrumenter.java Fri Apr 25 16:21:07 2014 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,46 +0,0 @@ -/* - * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * 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.truffle.api.nodes.instrument; - -import com.oracle.truffle.api.nodes.*; - -/** - * Implements the instrumentation of a Truffle AST node and returning either: - *

    - *
  • the node itself, or
  • - *
  • a newly created {@linkplain InstrumentationProxyNode proxy node} that holds the instrumented - * node as its {@linkplain com.oracle.truffle.api.nodes.Node.Child child}.
  • - *
- */ -public interface NodeInstrumenter { - - /** - * Wraps a {@linkplain InstrumentationProxyNode proxy node} around a node (if not already - * wrapped), marks the location with a {@linkplain NodePhylum phylum (category)} for user - * interaction, and passes along any characteristics of the particular node that are important - * for instrumentation (e.g. the function/method name at a call). - */ - Node instrumentAs(Node node, NodePhylum phylum, Object... args); -} diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/instrument/NodePhylum.java --- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/instrument/NodePhylum.java Fri Apr 25 16:21:07 2014 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,65 +0,0 @@ -/* - * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * 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.truffle.api.nodes.instrument; - -/** - * Categories of {@link InstrumentationProxyNode}s to be used for defining user-visible debugging - * and other simple tool behavior. These categories (phyla) should correspond to program - * structures that are meaningful to a programmer using the guest language. A Truffle node without a - * proxy carrying some phylum should be treated as an artifact of the guest language implementation - * and should never be visible to the user of a guest language programming tool. - *

- * Note that phyla are not intended to represent a partition of user-visible node categories, as the - * relative categorization of nodes can change with the particular programming tasks at hand. - *

- * This is a somewhat language-agnostic set of phyla, suitable for conventional imperative - * languages, and is being developed incrementally. - *

- * The need for alternative sets of phyla is likely to arise, perhaps for other families of - * languages (for example for mostly expression-oriented languages) or even for specific languages. - *

- * These are listed alphabetically so that listing from some collection classes will come out in - * that order. - *

- * Disclaimer: this interface is under development and will change. - */ -public enum NodePhylum { - - /** - * Marker for a proxy at a variable assignment. - */ - ASSIGNMENT, - - /** - * Marker for a proxy at a call site. - */ - CALL, - - /** - * Marker for a proxy at which ordinary "stepping" should halt. - */ - STATEMENT; - -} diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/instrument/PhylumMarked.java --- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/instrument/PhylumMarked.java Fri Apr 25 16:21:07 2014 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,46 +0,0 @@ -/* - * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * 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.truffle.api.nodes.instrument; - -import java.util.*; - -import com.oracle.truffle.api.nodes.*; - -/** - * A kind of {@link Node} that can be marked as belong to 0 or more {@linkplain NodePhylum phyla}. - */ -public interface PhylumMarked { - - /** - * Is this proxy tagged as belonging to a particular category of language constructs? - */ - boolean isMarkedAs(NodePhylum phylum); - - /** - * In which categories is this node tagged (empty set if none). - */ - Set getPhylumMarks(); - -} diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.truffle.api/src/com/oracle/truffle/api/source/SourceManager.java --- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/source/SourceManager.java Fri Apr 25 16:21:07 2014 +0200 +++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/source/SourceManager.java Mon Apr 28 11:18:15 2014 +0200 @@ -70,7 +70,7 @@ /** * Gets the canonical representation of a source file, whose contents will be read lazily and * then cached. - * + * * @param reset forces any existing {@link Source} cache to be cleared, forcing a re-read */ public Source get(String fileName, boolean reset) { @@ -227,6 +227,11 @@ } @Override + public String getShortName() { + return name; + } + + @Override public String getCode() { return code; } @@ -292,6 +297,11 @@ } @Override + public String getShortName() { + return file.getName(); + } + + @Override public String getCode() { if (code == null || timeStamp != file.lastModified()) { try { diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.truffle.sl.test/tests/HelloEqualsWorld.output diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.truffle.sl.test/tests/HelloEqualsWorld.sl --- a/graal/com.oracle.truffle.sl.test/tests/HelloEqualsWorld.sl Fri Apr 25 16:21:07 2014 +0200 +++ b/graal/com.oracle.truffle.sl.test/tests/HelloEqualsWorld.sl Mon Apr 28 11:18:15 2014 +0200 @@ -19,4 +19,4 @@ doIt(i); i = i + 1; } -} +} diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/builtins/SLHelloEqualsWorldBuiltin.java --- a/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/builtins/SLHelloEqualsWorldBuiltin.java Fri Apr 25 16:21:07 2014 +0200 +++ b/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/builtins/SLHelloEqualsWorldBuiltin.java Mon Apr 28 11:18:15 2014 +0200 @@ -35,11 +35,11 @@ public abstract class SLHelloEqualsWorldBuiltin extends SLBuiltinNode { @Specialization - public Object change() { + public String change() { FrameInstance frameInstance = Truffle.getRuntime().getStackTrace().iterator().next(); Frame frame = frameInstance.getFrame(FrameAccess.READ_WRITE, false); FrameSlot slot = frame.getFrameDescriptor().findOrAddFrameSlot("hello"); frame.setObject(slot, "world"); - return null; + return "world"; } } diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/builtins/SLStackTraceBuiltin.java --- a/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/builtins/SLStackTraceBuiltin.java Fri Apr 25 16:21:07 2014 +0200 +++ b/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/builtins/SLStackTraceBuiltin.java Mon Apr 28 11:18:15 2014 +0200 @@ -45,13 +45,17 @@ @SlowPath private static String createStackTrace() { StringBuilder str = new StringBuilder(); - for (FrameInstance frame : Truffle.getRuntime().getStackTrace()) { - dumpFrame(str, frame.getCallNode().getRootNode(), frame.getFrame(FrameAccess.READ_ONLY, true), frame.isVirtualFrame()); + Iterable frames = Truffle.getRuntime().getStackTrace(); + + if (frames != null) { + for (FrameInstance frame : frames) { + dumpFrame(str, frame.getCallTarget(), frame.getFrame(FrameAccess.READ_ONLY, true), frame.isVirtualFrame()); + } } return str.toString(); } - private static void dumpFrame(StringBuilder str, RootNode rootNode, Frame frame, boolean isVirtual) { + private static void dumpFrame(StringBuilder str, CallTarget rootNode, Frame frame, boolean isVirtual) { if (str.length() > 0) { str.append("\n"); } diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/call/SLDirectDispatchNode.java --- a/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/call/SLDirectDispatchNode.java Fri Apr 25 16:21:07 2014 +0200 +++ b/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/call/SLDirectDispatchNode.java Mon Apr 28 11:18:15 2014 +0200 @@ -36,11 +36,11 @@ private final SLFunction cachedFunction; /** - * {@link CallNode} is part of the Truffle API and handles all the steps necessary for method - * inlining: if the call is executed frequently and the callee is small, then the call is + * {@link DirectCallNode} is part of the Truffle API and handles all the steps necessary for + * method inlining: if the call is executed frequently and the callee is small, then the call is * inlined, i.e., the call node is replaced with a copy of the callee's AST. */ - @Child private CallNode callCachedTargetNode; + @Child private DirectCallNode callCachedTargetNode; /** Assumption that the {@link #callCachedTargetNode} is still valid. */ private final Assumption cachedTargetStable; @@ -53,7 +53,7 @@ protected SLDirectDispatchNode(SLAbstractDispatchNode next, SLFunction cachedFunction) { this.cachedFunction = cachedFunction; - this.callCachedTargetNode = Truffle.getRuntime().createCallNode(cachedFunction.getCallTarget()); + this.callCachedTargetNode = Truffle.getRuntime().createDirectCallNode(cachedFunction.getCallTarget()); this.cachedTargetStable = cachedFunction.getCallTargetStable(); this.nextNode = next; } diff -r 3dde8d8c95b8 -r 40d0022115ee graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/call/SLGenericDispatchNode.java --- a/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/call/SLGenericDispatchNode.java Fri Apr 25 16:21:07 2014 +0200 +++ b/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/call/SLGenericDispatchNode.java Mon Apr 28 11:18:15 2014 +0200 @@ -22,19 +22,23 @@ */ package com.oracle.truffle.sl.nodes.call; -import com.oracle.truffle.api.CompilerDirectives.CompilationFinal; +import com.oracle.truffle.api.*; import com.oracle.truffle.api.frame.*; -import com.oracle.truffle.api.frame.FrameInstance.FrameAccess; -import com.oracle.truffle.api.impl.*; +import com.oracle.truffle.api.nodes.*; import com.oracle.truffle.sl.runtime.*; /** * Slow-path code for a call, used when the polymorphic inline cache exceeded its maximum size. Such * calls are not optimized any further, e.g., no method inlining is performed. */ -final class SLGenericDispatchNode extends SLAbstractDispatchNode implements MaterializedFrameNotify { +final class SLGenericDispatchNode extends SLAbstractDispatchNode { - @CompilationFinal private FrameAccess outsideFrameAccess = FrameAccess.NONE; + /** + * {@link IndirectCallNode} is part of the Truffle API and handles all the steps necessary for + * calling a megamorphic call-site. The Graal specific version of this node performs additional + * optimizations for the fast access of the SimpleLanguage stack trace. + */ + @Child private IndirectCallNode callNode = Truffle.getRuntime().createIndirectCallNode(); @Override protected Object executeDispatch(VirtualFrame frame, SLFunction function, Object[] arguments) { @@ -42,14 +46,7 @@ * SL has a quite simple call lookup: just ask the function for the current call target, and * call it. */ - return DefaultCallNode.callProxy(this, function.getCallTarget(), frame, arguments); + return callNode.call(frame, function.getCallTarget(), arguments); } - public FrameAccess getOutsideFrameAccess() { - return outsideFrameAccess; - } - - public void setOutsideFrameAccess(FrameAccess outsideFrameAccess) { - this.outsideFrameAccess = outsideFrameAccess; - } } diff -r 3dde8d8c95b8 -r 40d0022115ee make/linux/makefiles/buildtree.make --- a/make/linux/makefiles/buildtree.make Fri Apr 25 16:21:07 2014 +0200 +++ b/make/linux/makefiles/buildtree.make Mon Apr 28 11:18:15 2014 +0200 @@ -258,6 +258,10 @@ echo "$(call gamma-path,altsrc,os/$(OS_FAMILY)/vm) \\"; \ echo "$(call gamma-path,commonsrc,os/$(OS_FAMILY)/vm) \\"; \ echo "$(call gamma-path,commonsrc,os/posix/vm) \\"; \ + echo "$(call gamma-path,altsrc,gpu/ptx/vm) \\"; \ + echo "$(call gamma-path,commonsrc,gpu/ptx/vm)" \\; \ + echo "$(call gamma-path,altsrc,gpu/hsail/vm) \\"; \ + echo "$(call gamma-path,commonsrc,gpu/hsail/vm) \\"; \ echo "$(call gamma-path,altsrc,gpu) \\"; \ echo "$(call gamma-path,commonsrc,gpu)"; \ [ -n "$(CFLAGS_BROWSE)" ] && \ diff -r 3dde8d8c95b8 -r 40d0022115ee make/linux/makefiles/vm.make --- a/make/linux/makefiles/vm.make Fri Apr 25 16:21:07 2014 +0200 +++ b/make/linux/makefiles/vm.make Mon Apr 28 11:18:15 2014 +0200 @@ -185,8 +185,10 @@ GRAAL_PATHS += $(call altsrc,$(HS_COMMON_SRC)/share/vm/graal) GRAAL_PATHS += $(call altsrc,$(HS_COMMON_SRC)/gpu/ptx/vm) +GRAAL_PATHS += $(call altsrc,$(HS_COMMON_SRC)/gpu/hsail/vm) GRAAL_PATHS += $(HS_COMMON_SRC)/share/vm/graal GRAAL_PATHS += $(HS_COMMON_SRC)/gpu/ptx/vm +GRAAL_PATHS += $(HS_COMMON_SRC)/gpu/hsail/vm # Include dirs per type. Src_Dirs/CORE := $(CORE_PATHS) diff -r 3dde8d8c95b8 -r 40d0022115ee make/solaris/makefiles/mapfile-vers --- a/make/solaris/makefiles/mapfile-vers Fri Apr 25 16:21:07 2014 +0200 +++ b/make/solaris/makefiles/mapfile-vers Mon Apr 28 11:18:15 2014 +0200 @@ -223,8 +223,6 @@ JVM_SetLength; JVM_SetNativeThreadName; JVM_SetPrimitiveArrayElement; - # Preserved so that Graal repo can link against a JDK7 libjava.so works - JVM_SetProtectionDomain; JVM_SetSockOpt; JVM_SetThreadPriority; JVM_Sleep; diff -r 3dde8d8c95b8 -r 40d0022115ee mx/eclipse-settings/org.eclipse.jdt.core.prefs --- a/mx/eclipse-settings/org.eclipse.jdt.core.prefs Fri Apr 25 16:21:07 2014 +0200 +++ b/mx/eclipse-settings/org.eclipse.jdt.core.prefs Mon Apr 28 11:18:15 2014 +0200 @@ -100,7 +100,6 @@ org.eclipse.jdt.core.compiler.problem.suppressWarnings=enabled org.eclipse.jdt.core.compiler.problem.syntheticAccessEmulation=ignore org.eclipse.jdt.core.compiler.problem.typeParameterHiding=warning -org.eclipse.jdt.core.compiler.problem.tasks=ignore org.eclipse.jdt.core.compiler.problem.unavoidableGenericTypeProblems=enabled org.eclipse.jdt.core.compiler.problem.uncheckedTypeOperation=warning org.eclipse.jdt.core.compiler.problem.unclosedCloseable=ignore diff -r 3dde8d8c95b8 -r 40d0022115ee mx/mx_graal.py --- a/mx/mx_graal.py Fri Apr 25 16:21:07 2014 +0200 +++ b/mx/mx_graal.py Mon Apr 28 11:18:15 2014 +0200 @@ -28,13 +28,14 @@ import os, sys, shutil, zipfile, tempfile, re, time, datetime, platform, subprocess, multiprocessing, StringIO from os.path import join, exists, dirname, basename, getmtime -from argparse import ArgumentParser, REMAINDER +from argparse import ArgumentParser, RawDescriptionHelpFormatter, REMAINDER from outputparser import OutputParser, ValuesMatcher import mx import xml.dom.minidom import sanitycheck import itertools import json, textwrap +import fnmatch # This works because when mx loads this file, it makes sure __file__ gets an absolute path _graal_home = dirname(dirname(__file__)) @@ -828,7 +829,7 @@ else: return [], args -def _run_tests(args, harness, annotations, testfile): +def _run_tests(args, harness, annotations, testfile, whitelist): vmArgs, tests = _extract_VM_args(args) @@ -860,6 +861,9 @@ mx.log('warning: no tests matched by substring "' + t) projectscp = mx.classpath(projs) + if whitelist: + classes = [c for c in classes if any((glob.match(c) for glob in whitelist))] + if len(classes) != 0: f_testfile = open(testfile, 'w') for c in classes: @@ -867,7 +871,7 @@ f_testfile.close() harness(projectscp, vmArgs) -def _unittest(args, annotations, prefixcp=""): +def _unittest(args, annotations, prefixcp="", whitelist=None): mxdir = dirname(__file__) name = 'JUnitWrapper' javaSource = join(mxdir, name + '.java') @@ -894,12 +898,18 @@ vm(prefixArgs + vmArgs + ['-cp', prefixcp + projectscp + os.pathsep + mxdir, name] + [testfile]) try: - _run_tests(args, harness, annotations, testfile) + _run_tests(args, harness, annotations, testfile, whitelist) finally: if os.environ.get('MX_TESTFILE') is None: os.remove(testfile) _unittestHelpSuffix = """ + Unittest options: + + --whitelist run only testcases which are included + in the given whitelist + + To avoid conflicts with VM options '--' can be used as delimiter. If filters are supplied, only tests whose fully qualified name includes a filter as a substring are run. @@ -928,17 +938,46 @@ def unittest(args): """run the JUnit tests (all testcases){0}""" - _unittest(args, ['@Test', '@LongTest', '@Parameters']) + parser = ArgumentParser(prog='mx unittest', + description='run the JUnit tests', + add_help=False, + formatter_class=RawDescriptionHelpFormatter, + epilog=_unittestHelpSuffix, + ) + parser.add_argument('--whitelist', help='run testcases specified in whitelist only', metavar='') + + ut_args = [] + delimiter = False + # check for delimiter + while len(args) > 0: + arg = args.pop(0) + if arg == '--': + delimiter = True + break + ut_args.append(arg) + + if delimiter: + # all arguments before '--' must be recognized + parsed_args = parser.parse_args(ut_args) + else: + # parse all know arguments + parsed_args, args = parser.parse_known_args(ut_args) + + whitelist = None + if parsed_args.whitelist: + try: + with open(join(_graal_home, parsed_args.whitelist)) as fp: + whitelist = [re.compile(fnmatch.translate(l.rstrip())) for l in fp.readlines() if not l.startswith('#')] + except IOError: + mx.log('warning: could not read whitelist: ' + parsed_args.whitelist) + + _unittest(args, ['@Test', '@Parameters'], whitelist=whitelist) def shortunittest(args): - """run the JUnit tests (short testcases only){0}""" - - _unittest(args, ['@Test']) + """alias for 'unittest --whitelist test/whitelist_shortunittest.txt'{0}""" -def longunittest(args): - """run the JUnit tests (long testcases only){0}""" - - _unittest(args, ['@LongTest', '@Parameters']) + args = ['--whitelist', 'test/whitelist_shortunittest.txt'] + args + unittest(args) def buildvms(args): """build one or more VMs in various configurations""" @@ -1047,6 +1086,11 @@ unittest([]) tasks.append(t.stop()) + with VM('server', 'product'): # hosted mode + t = Task('UnitTests-BaselineCompiler:hosted-product') + unittest(['--whitelist', 'test/whitelist_baseline.txt', '-G:+UseBaselineCompiler']) + tasks.append(t.stop()) + for vmbuild in ['fastdebug', 'product']: for test in sanitycheck.getDacapos(level=sanitycheck.SanityCheckLevel.Gate, gateBuildLevel=vmbuild) + sanitycheck.getScalaDacapos(level=sanitycheck.SanityCheckLevel.Gate, gateBuildLevel=vmbuild): t = Task(str(test) + ':' + vmbuild) @@ -1248,10 +1292,10 @@ else: executable = join(libpath, 'c1visualizer', 'bin', 'c1visualizer') - archive = join(libpath, 'c1visualizer.zip') - if not exists(executable): + archive = join(libpath, 'c1visualizer_2014-04-22.zip') + if not exists(executable) or not exists(archive): if not exists(archive): - mx.download(archive, ['https://java.net/downloads/c1visualizer/c1visualizer.zip']) + mx.download(archive, ['https://java.net/downloads/c1visualizer/c1visualizer_2014-04-22.zip']) zf = zipfile.ZipFile(archive, 'r') zf.extractall(libpath) @@ -1345,17 +1389,140 @@ with open(resultFile, 'w') as f: f.write(json.dumps(results)) +def _get_jmh_path(): + path = mx.get_env('JMH_BENCHMARKS', None) + if not path: + probe = join(dirname(_graal_home), 'java-benchmarks') + if exists(probe): + path = probe + + if not path: + mx.abort("Please set the JMH_BENCHMARKS environment variable to point to the java-benchmarks workspace") + if not exists(path): + mx.abort("The directory denoted by the JMH_BENCHMARKS environment variable does not exist: " + path) + return path + +def makejmhdeps(args): + """creates and installs Maven dependencies required by the JMH benchmarks + + The dependencies are specified by files named pom.mxdeps in the + JMH directory tree. Each such file contains a list of dependencies + defined in JSON format. For example: + + '[{"artifactId" : "compiler.test", "groupId" : "com.oracle.graal", "deps" : ["com.oracle.graal.compiler.test"]}]' + + will result in a dependency being installed in the local Maven repository + that can be referenced in a pom.xml file as follows: + + + com.oracle.graal + compiler.test + 1.0-SNAPSHOT + """ + + parser = ArgumentParser(prog='mx makejmhdeps') + parser.add_argument('-s', '--settings', help='alternative path for Maven user settings file', metavar='') + parser.add_argument('-p', '--permissive', action='store_true', help='issue note instead of error if a Maven dependency cannot be built due to missing projects/libraries') + args = parser.parse_args(args) + + def makejmhdep(artifactId, groupId, deps): + graalSuite = mx.suite("graal") + path = artifactId + '.jar' + if args.permissive: + for name in deps: + if not mx.project(name, fatalIfMissing=False): + if not mx.library(name, fatalIfMissing=False): + mx.log('Skipping ' + groupId + '.' + artifactId + '.jar as ' + name + ' cannot be resolved') + return + d = mx.Distribution(graalSuite, name=artifactId, path=path, sourcesPath=path, deps=deps, excludedLibs=[]) + d.make_archive() + cmd = ['mvn', 'install:install-file', '-DgroupId=' + groupId, '-DartifactId=' + artifactId, + '-Dversion=1.0-SNAPSHOT', '-Dpackaging=jar', '-Dfile=' + d.path] + if not mx._opts.verbose: + cmd.append('-q') + if args.settings: + cmd = cmd + ['-s', args.settings] + mx.run(cmd) + os.unlink(d.path) + + jmhPath = _get_jmh_path() + for root, _, filenames in os.walk(jmhPath): + for f in [join(root, n) for n in filenames if n == 'pom.mxdeps']: + mx.logv('[processing ' + f + ']') + try: + with open(f) as fp: + for d in json.load(fp): + artifactId = d['artifactId'] + groupId = d['groupId'] + deps = d['deps'] + makejmhdep(artifactId, groupId, deps) + except ValueError as e: + mx.abort('Error parsing {}:\n{}'.format(f, e)) + +def buildjmh(args): + """build the JMH benchmarks""" + + parser = ArgumentParser(prog='mx buildjmh') + parser.add_argument('-s', '--settings', help='alternative path for Maven user settings file', metavar='') + parser.add_argument('-c', action='store_true', dest='clean', help='clean before building') + args = parser.parse_args(args) + + jmhPath = _get_jmh_path() + mx.log('JMH benchmarks: ' + jmhPath) + + # Ensure the mx injected dependencies are up to date + makejmhdeps(['-p'] + (['-s', args.settings] if args.settings else [])) + + timestamp = mx.TimeStampFile(join(_graal_home, 'mx', 'jmh', jmhPath.replace(os.sep, '_') + '.timestamp')) + mustBuild = args.clean + if not mustBuild: + try: + hgfiles = [join(jmhPath, f) for f in subprocess.check_output(['hg', '-R', jmhPath, 'locate']).split('\n')] + mustBuild = timestamp.isOlderThan(hgfiles) + except: + # not a Mercurial repository or hg commands are not available. + mustBuild = True + + if mustBuild: + buildOutput = [] + def _redirect(x): + if mx._opts.verbose: + mx.log(x[:-1]) + else: + buildOutput.append(x) + env = os.environ.copy() + env['JAVA_HOME'] = _jdk(vmToCheck='server') + env['MAVEN_OPTS'] = '-server' + mx.log("Building benchmarks...") + cmd = ['mvn'] + if args.settings: + cmd = cmd + ['-s', args.settings] + if args.clean: + cmd.append('clean') + cmd.append('package') + retcode = mx.run(cmd, cwd=jmhPath, out=_redirect, env=env, nonZeroIsFatal=False) + if retcode != 0: + mx.log(''.join(buildOutput)) + mx.abort(retcode) + timestamp.touch() + else: + mx.logv('[all Mercurial controlled files in ' + jmhPath + ' are older than ' + timestamp.path + ' - skipping build]') + def jmh(args): - """run the JMH_BENCHMARKS""" + """run the JMH benchmarks - # TODO: add option for `mvn clean package' + This command respects the standard --vm and --vmbuild options + for choosing which VM to run the benchmarks with.""" + if '-h' in args: + mx.help_(['jmh']) + mx.abort(1) vmArgs, benchmarksAndJsons = _extract_VM_args(args) benchmarks = [b for b in benchmarksAndJsons if not b.startswith('{')] jmhArgJsons = [b for b in benchmarksAndJsons if b.startswith('{')] - jmhArgs = {'-v' : 'EXTRA' if mx._opts.verbose else 'NORMAL'} + jmhArgs = {'-rff' : join(_graal_home, 'mx', 'jmh', 'jmh.out'), '-v' : 'EXTRA' if mx._opts.verbose else 'NORMAL'} # e.g. '{"-wi" : 20}' for j in jmhArgJsons: @@ -1366,21 +1533,10 @@ else: jmhArgs[n] = v except ValueError as e: - mx.abort('error parsing JSON input: {}"\n{}'.format(j, e)) - - jmhPath = mx.get_env('JMH_BENCHMARKS', None) - if not jmhPath or not exists(jmhPath): - mx.abort("$JMH_BENCHMARKS not properly defined: " + str(jmhPath)) + mx.abort('error parsing JSON input: {}\n{}'.format(j, e)) - def _blackhole(x): - mx.logv(x[:-1]) - - - env = os.environ.copy() - env['JAVA_HOME'] = _jdk(vmToCheck='graal') - env['MAVEN_OPTS'] = '-graal' - mx.log("Building benchmarks...") - mx.run(['mvn', 'package'], cwd=jmhPath, out=_blackhole, env=env) + jmhPath = _get_jmh_path() + mx.log('Using benchmarks in ' + jmhPath) matchedSuites = set() numBench = [0] @@ -1394,8 +1550,7 @@ microJar = os.path.join(absoluteMicro, "target", "microbenchmarks.jar") if not exists(microJar): - mx.logv('JMH: ignored ' + absoluteMicro + " because it doesn't contain the expected jar file ('" + microJar + "')") - continue + mx.abort('Missing ' + microJar + ' - please run "mx buildjmh"') if benchmarks: def _addBenchmark(x): if x.startswith("Benchmark:"): @@ -1435,7 +1590,6 @@ javaArgs.append(str(v)) mx.run_java(javaArgs + regex, addDefaultArgs=False, cwd=jmhPath) - def specjvm2008(args): """run one or more SPECjvm2008 benchmarks""" @@ -1556,14 +1710,14 @@ """make truffle.jar""" # Test with the built classes - _unittest(["com.oracle.truffle.api.test", "com.oracle.truffle.api.dsl.test"], ['@Test', '@LongTest', '@Parameters']) + _unittest(["com.oracle.truffle.api.test", "com.oracle.truffle.api.dsl.test"], ['@Test', '@Parameters']) # We use the DSL processor as the starting point for the classpath - this # therefore includes the DSL processor, the DSL and the API. packagejar(mx.classpath("com.oracle.truffle.dsl.processor").split(os.pathsep), "truffle.jar", None, "com.oracle.truffle.dsl.processor.TruffleProcessor") # Test with the JAR - _unittest(["com.oracle.truffle.api.test", "com.oracle.truffle.api.dsl.test"], ['@Test', '@LongTest', '@Parameters'], "truffle.jar:") + _unittest(["com.oracle.truffle.api.test", "com.oracle.truffle.api.dsl.test"], ['@Test', '@Parameters'], "truffle.jar:") def isGraalEnabled(vm): @@ -1765,6 +1919,7 @@ def mx_init(suite): commands = { 'build': [build, ''], + 'buildjmh': [buildjmh, '[-options]'], 'buildvars': [buildvars, ''], 'buildvms': [buildvms, '[-options]'], 'c1visualizer' : [c1visualizer, ''], @@ -1784,9 +1939,9 @@ 'specjbb2005': [specjbb2005, '[VM options] [-- [SPECjbb2005 options]]'], 'gate' : [gate, '[-options]'], 'bench' : [bench, '[-resultfile file] [all(default)|dacapo|specjvm2008|bootstrap]'], - 'unittest' : [unittest, '[VM options] [filters...]', _unittestHelpSuffix], - 'longunittest' : [longunittest, '[VM options] [filters...]', _unittestHelpSuffix], - 'shortunittest' : [shortunittest, '[VM options] [filters...]', _unittestHelpSuffix], + 'unittest' : [unittest, '[unittest options] [--] [VM options] [filters...]', _unittestHelpSuffix], + 'makejmhdeps' : [makejmhdeps, ''], + 'shortunittest' : [shortunittest, '[unittest options] [--] [VM options] [filters...]', _unittestHelpSuffix], 'jacocoreport' : [jacocoreport, '[output directory]'], 'site' : [site, '[-options]'], 'vm': [vm, '[-options] class [args...]'], diff -r 3dde8d8c95b8 -r 40d0022115ee mx/projects --- a/mx/projects Fri Apr 25 16:21:07 2014 +0200 +++ b/mx/projects Mon Apr 28 11:18:15 2014 +0200 @@ -5,10 +5,21 @@ library@JDK_TOOLS@path=${JAVA_HOME}/lib/tools.jar library@JDK_TOOLS@optional=true -library@JUNIT@path=lib/junit-4.8.jar -library@JUNIT@urls=http://repo1.maven.org/maven2/junit/junit/4.8/junit-4.8.jar -library@JUNIT@sha1=4150c00c5706306ef0f8f1410e70c8ff12757922 +library@JUNIT@path=lib/junit-4.11.jar +library@JUNIT@urls=http://repo1.maven.org/maven2/junit/junit/4.11/junit-4.11.jar +library@JUNIT@sha1=4e031bb61df09069aeb2bffb4019e7a5034a4ee0 library@JUNIT@eclipse.container=org.eclipse.jdt.junit.JUNIT_CONTAINER/4 +library@JUNIT@sourcePath=lib/junit-4.11-sources.jar +library@JUNIT@sourceUrls=http://repo1.maven.org/maven2/junit/junit/4.11/junit-4.11-sources.jar +library@JUNIT@sourceSha1=28e0ad201304e4a4abf999ca0570b7cffc352c3c +library@JUNIT@dependencies=HAMCREST + +library@HAMCREST@path=lib/hamcrest-core-1.3.jar +library@HAMCREST@urls=http://repo1.maven.org/maven2/org/hamcrest/hamcrest-core/1.3/hamcrest-core-1.3.jar +library@HAMCREST@sha1=42a25dc3219429f0e5d060061f71acb49bf010a0 +library@HAMCREST@sourcePath=lib/hamcrest-core-1.3-sources.jar +library@HAMCREST@sourceUrls=http://repo1.maven.org/maven2/org/hamcrest/hamcrest-core/1.3/hamcrest-core-1.3-sources.jar +library@HAMCREST@sourceSha1=1dc37250fbc78e23a65a67fbbaf71d2e9cbc3c0b library@CHECKSTYLE@path=lib/checkstyle-5.5-all.jar library@CHECKSTYLE@urls=jar:http://sourceforge.net/projects/checkstyle/files/checkstyle/5.5/checkstyle-5.5-bin.zip/download!/checkstyle-5.5/checkstyle-5.5-all.jar @@ -31,20 +42,23 @@ library@DACAPO_SCALA@urls=http://repo.scalabench.org/snapshots/org/scalabench/benchmarks/scala-benchmark-suite/0.1.0-SNAPSHOT/scala-benchmark-suite-0.1.0-20120216.103539-3.jar library@DACAPO_SCALA@sha1=59b64c974662b5cf9dbd3cf9045d293853dd7a51 -library@OKRA@path=lib/okra-1.8.jar -library@OKRA@urls=http://cr.openjdk.java.net/~tdeneau/okra-1.8.jar -library@OKRA@sourcePath=lib/okra-1.8-src.jar -library@OKRA@sourceUrls=http://cr.openjdk.java.net/~tdeneau/okra-1.8-src.jar +library@OKRA@path=lib/okra-1.9.jar +library@OKRA@urls=http://cr.openjdk.java.net/~tdeneau/okra-1.9.jar +library@OKRA@sourcePath=lib/okra-1.9-src.jar +library@OKRA@sourceUrls=http://cr.openjdk.java.net/~tdeneau/okra-1.9-src.jar -library@OKRA_WITH_SIM@path=lib/okra-1.8-with-sim.jar -library@OKRA_WITH_SIM@urls=http://cr.openjdk.java.net/~tdeneau/okra-1.8-with-sim.jar -library@OKRA_WITH_SIM@sourcePath=lib/okra-1.8-with-sim-src.jar -library@OKRA_WITH_SIM@sourceUrls=http://cr.openjdk.java.net/~tdeneau/okra-1.8-with-sim-src.jar +library@OKRA_WITH_SIM@path=lib/okra-1.9-with-sim.jar +library@OKRA_WITH_SIM@urls=http://cr.openjdk.java.net/~tdeneau/okra-1.9-with-sim.jar +library@OKRA_WITH_SIM@sourcePath=lib/okra-1.9-with-sim-src.jar +library@OKRA_WITH_SIM@sourceUrls=http://cr.openjdk.java.net/~tdeneau/okra-1.9-with-sim-src.jar library@JAVA_ALLOCATION_INSTRUMENTER@path=lib/java-allocation-instrumenter.jar library@JAVA_ALLOCATION_INSTRUMENTER@urls=http://lafo.ssw.uni-linz.ac.at/java-allocation-instrumenter/java-allocation-instrumenter-8f0db117e64e.jar library@JAVA_ALLOCATION_INSTRUMENTER@sha1=64c0a5329fbcb8284640e58d83252e0a3b08c23e +library@VECMATH@path=lib/vecmath-1.3.1.jar +library@VECMATH@urls=http://mirrors.ibiblio.org/pub/mirrors/maven/java3d/jars/vecmath-1.3.1.jar + distribution@GRAAL@path=graal.jar distribution@GRAAL@sourcesPath=graal.src.zip distribution@GRAAL@dependencies=\ @@ -239,7 +253,7 @@ # graal.graph project@com.oracle.graal.graph@subDir=graal project@com.oracle.graal.graph@sourceDirs=src -project@com.oracle.graal.graph@dependencies=com.oracle.graal.debug,com.oracle.graal.api.code,FINDBUGS +project@com.oracle.graal.graph@dependencies=com.oracle.graal.debug,com.oracle.graal.compiler.common,FINDBUGS project@com.oracle.graal.graph@javaCompliance=1.8 project@com.oracle.graal.graph@workingSets=Graal,Graph @@ -269,7 +283,7 @@ # graal.lir project@com.oracle.graal.lir@subDir=graal project@com.oracle.graal.lir@sourceDirs=src -project@com.oracle.graal.lir@dependencies=com.oracle.graal.asm,com.oracle.graal.nodes +project@com.oracle.graal.lir@dependencies=com.oracle.graal.debug,com.oracle.graal.compiler.common,com.oracle.graal.asm project@com.oracle.graal.lir@checkstyle=com.oracle.graal.graph project@com.oracle.graal.lir@javaCompliance=1.8 project@com.oracle.graal.lir@workingSets=Graal,LIR @@ -359,7 +373,7 @@ # graal.nodes project@com.oracle.graal.nodes@subDir=graal project@com.oracle.graal.nodes@sourceDirs=src -project@com.oracle.graal.nodes@dependencies=com.oracle.graal.graph,com.oracle.graal.api.replacements +project@com.oracle.graal.nodes@dependencies=com.oracle.graal.graph,com.oracle.graal.api.replacements,com.oracle.graal.lir project@com.oracle.graal.nodes@checkstyle=com.oracle.graal.graph project@com.oracle.graal.nodes@javaCompliance=1.8 project@com.oracle.graal.nodes@annotationProcessors=com.oracle.graal.replacements.verifier @@ -376,7 +390,7 @@ # graal.phases project@com.oracle.graal.phases@subDir=graal project@com.oracle.graal.phases@sourceDirs=src -project@com.oracle.graal.phases@dependencies=com.oracle.graal.nodes,com.oracle.graal.options +project@com.oracle.graal.phases@dependencies=com.oracle.graal.nodes project@com.oracle.graal.phases@checkstyle=com.oracle.graal.graph project@com.oracle.graal.phases@javaCompliance=1.8 project@com.oracle.graal.phases@workingSets=Graal,Phases @@ -408,10 +422,11 @@ # graal.compiler project@com.oracle.graal.compiler@subDir=graal project@com.oracle.graal.compiler@sourceDirs=src -project@com.oracle.graal.compiler@dependencies=com.oracle.graal.api.runtime,com.oracle.graal.virtual,com.oracle.graal.loop,com.oracle.graal.alloc,com.oracle.graal.lir +project@com.oracle.graal.compiler@dependencies=com.oracle.graal.api.runtime,com.oracle.graal.virtual,com.oracle.graal.loop,com.oracle.graal.alloc project@com.oracle.graal.compiler@checkstyle=com.oracle.graal.graph project@com.oracle.graal.compiler@javaCompliance=1.8 project@com.oracle.graal.compiler@annotationProcessors=com.oracle.graal.service.processor +project@com.oracle.graal.compiler@annotationProcessorForDependents=true project@com.oracle.graal.compiler@workingSets=Graal # graal.compiler.amd64 @@ -485,6 +500,14 @@ project@com.oracle.graal.java@javaCompliance=1.8 project@com.oracle.graal.java@workingSets=Graal,Java +# graal.compiler.common +project@com.oracle.graal.compiler.common@subDir=graal +project@com.oracle.graal.compiler.common@sourceDirs=src +project@com.oracle.graal.compiler.common@dependencies=com.oracle.graal.api.code,com.oracle.graal.options +project@com.oracle.graal.compiler.common@checkstyle=com.oracle.graal.graph +project@com.oracle.graal.compiler.common@javaCompliance=1.8 +project@com.oracle.graal.compiler.common@workingSets=Graal,Java + # graal.baseline project@com.oracle.graal.baseline@subDir=graal project@com.oracle.graal.baseline@sourceDirs=src @@ -611,14 +634,14 @@ # graal.compiler.hsail.test project@com.oracle.graal.compiler.hsail.test@subDir=graal project@com.oracle.graal.compiler.hsail.test@sourceDirs=src -project@com.oracle.graal.compiler.hsail.test@dependencies=com.oracle.graal.compiler.hsail.test.infra,com.oracle.graal.compiler.test +project@com.oracle.graal.compiler.hsail.test@dependencies=com.oracle.graal.compiler.hsail.test.infra,com.oracle.graal.compiler.test,VECMATH project@com.oracle.graal.compiler.hsail.test@checkstyle=com.oracle.graal.graph project@com.oracle.graal.compiler.hsail.test@javaCompliance=1.8 # graal.asm.hsail project@com.oracle.graal.asm.hsail@subDir=graal project@com.oracle.graal.asm.hsail@sourceDirs=src -project@com.oracle.graal.asm.hsail@dependencies=com.oracle.graal.hsail,OKRA,com.oracle.graal.asm,com.oracle.graal.graph +project@com.oracle.graal.asm.hsail@dependencies=com.oracle.graal.hsail,OKRA,com.oracle.graal.asm,com.oracle.graal.compiler.common project@com.oracle.graal.asm.hsail@checkstyle=com.oracle.graal.graph project@com.oracle.graal.asm.hsail@javaCompliance=1.8 @@ -723,7 +746,7 @@ # graal.truffle.hotspot.amd64 project@com.oracle.graal.truffle.hotspot.amd64@subDir=graal project@com.oracle.graal.truffle.hotspot.amd64@sourceDirs=src -project@com.oracle.graal.truffle.hotspot.amd64@dependencies=com.oracle.graal.truffle.hotspot,com.oracle.graal.hotspot.amd64 +project@com.oracle.graal.truffle.hotspot.amd64@dependencies=com.oracle.graal.truffle.hotspot,com.oracle.graal.asm.amd64 project@com.oracle.graal.truffle.hotspot.amd64@checkstyle=com.oracle.graal.graph project@com.oracle.graal.truffle.hotspot.amd64@javaCompliance=1.8 project@com.oracle.graal.truffle.hotspot.amd64@annotationProcessors=com.oracle.graal.service.processor diff -r 3dde8d8c95b8 -r 40d0022115ee mxtool/mx.py --- a/mxtool/mx.py Fri Apr 25 16:21:07 2014 +0200 +++ b/mxtool/mx.py Mon Apr 28 11:18:15 2014 +0200 @@ -36,6 +36,7 @@ import sys, os, errno, time, subprocess, shlex, types, urllib2, contextlib, StringIO, zipfile, signal, xml.sax.saxutils, tempfile, fnmatch import textwrap import socket +import tarfile import hashlib import xml.parsers.expat import shutil, re, xml.dom.minidom @@ -84,6 +85,89 @@ def add_update_listener(self, listener): self.update_listeners.add(listener) + def make_archive(self): + # are sources combined into main archive? + unified = self.path == self.sourcesPath + + with Archiver(self.path) as arc, Archiver(None if unified else self.sourcesPath) as srcArcRaw: + srcArc = arc if unified else srcArcRaw + services = {} + def overwriteCheck(zf, arcname, source): + if not hasattr(zf, '_provenance'): + zf._provenance = {} + existingSource = zf._provenance.get(arcname, None) + if existingSource and existingSource != source and not arcname.endswith('/'): + log('warning: ' + self.path + ': overwriting ' + arcname + '\n new: ' + source + '\n old: ' + existingSource) + zf._provenance[arcname] = source + + for dep in self.sorted_deps(includeLibs=True): + if dep.isLibrary(): + l = dep + # merge library jar into distribution jar + logv('[' + self.path + ': adding library ' + l.name + ']') + lpath = l.get_path(resolve=True) + libSourcePath = l.get_source_path(resolve=True) + if lpath: + with zipfile.ZipFile(lpath, 'r') as lp: + for arcname in lp.namelist(): + if arcname.startswith('META-INF/services/') and not arcname == 'META-INF/services/': + service = arcname[len('META-INF/services/'):] + assert '/' not in service + services.setdefault(service, []).extend(lp.read(arcname).splitlines()) + else: + overwriteCheck(arc.zf, arcname, lpath + '!' + arcname) + arc.zf.writestr(arcname, lp.read(arcname)) + if srcArc.zf and libSourcePath: + with zipfile.ZipFile(libSourcePath, 'r') as lp: + for arcname in lp.namelist(): + overwriteCheck(srcArc.zf, arcname, lpath + '!' + arcname) + srcArc.zf.writestr(arcname, lp.read(arcname)) + else: + p = dep + # skip a Java project if its Java compliance level is "higher" than the configured JDK + jdk = java(p.javaCompliance) + if not jdk: + log('Excluding {0} from {2} (Java compliance level {1} required)'.format(p.name, p.javaCompliance, self.path)) + continue + + logv('[' + self.path + ': adding project ' + p.name + ']') + outputDir = p.output_dir() + for root, _, files in os.walk(outputDir): + relpath = root[len(outputDir) + 1:] + if relpath == join('META-INF', 'services'): + for service in files: + with open(join(root, service), 'r') as fp: + services.setdefault(service, []).extend([provider.strip() for provider in fp.readlines()]) + elif relpath == join('META-INF', 'providers'): + for provider in files: + with open(join(root, provider), 'r') as fp: + for service in fp: + services.setdefault(service.strip(), []).append(provider) + else: + for f in files: + arcname = join(relpath, f).replace(os.sep, '/') + overwriteCheck(arc.zf, arcname, join(root, f)) + arc.zf.write(join(root, f), arcname) + if srcArc.zf: + sourceDirs = p.source_dirs() + if p.source_gen_dir(): + sourceDirs.append(p.source_gen_dir()) + for srcDir in sourceDirs: + for root, _, files in os.walk(srcDir): + relpath = root[len(srcDir) + 1:] + for f in files: + if f.endswith('.java'): + arcname = join(relpath, f).replace(os.sep, '/') + overwriteCheck(srcArc.zf, arcname, join(root, f)) + srcArc.zf.write(join(root, f), arcname) + + for service, providers in services.iteritems(): + arcname = 'META-INF/services/' + service + arc.zf.writestr(arcname, '\n'.join(providers)) + + self.notify_updated() + + def notify_updated(self): for l in self.update_listeners: l(self) @@ -358,6 +442,18 @@ print >> fp, ap return outOfDate + def make_archive(self, path=None): + outputDir = self.output_dir() + if not path: + path = join(self.dir, self.name + '.jar') + with Archiver(path) as arc: + for root, _, files in os.walk(outputDir): + for f in files: + relpath = root[len(outputDir) + 1:] + arcname = join(relpath, f).replace(os.sep, '/') + arc.zf.write(join(root, f), arcname) + return path + def _make_absolute(path, prefix): """ Makes 'path' absolute if it isn't already by prefixing 'prefix' @@ -405,7 +501,7 @@ return path class Library(Dependency): - def __init__(self, suite, name, path, mustExist, urls, sha1, sourcePath, sourceUrls, sourceSha1): + def __init__(self, suite, name, path, mustExist, urls, sha1, sourcePath, sourceUrls, sourceSha1, deps): Dependency.__init__(self, suite, name) self.path = path.replace('/', os.sep) self.urls = urls @@ -414,6 +510,7 @@ self.sourcePath = sourcePath self.sourceUrls = sourceUrls self.sourceSha1 = sourceSha1 + self.deps = deps for url in urls: if url.endswith('/') != self.path.endswith(os.sep): abort('Path for dependency directory must have a URL ending with "/": path=' + self.path + ' url=' + url) @@ -447,9 +544,9 @@ def get_source_path(self, resolve): - if self.path is None: + if self.sourcePath is None: return None - path = _make_absolute(self.path, self.suite.dir) + path = _make_absolute(self.sourcePath, self.suite.dir) sha1path = path + '.sha1' return _download_file_with_sha1(self.name, path, self.sourceUrls, self.sourceSha1, sha1path, resolve, len(self.sourceUrls) != 0, sources=True) @@ -460,9 +557,21 @@ cp.append(path) def all_deps(self, deps, includeLibs, includeSelf=True, includeAnnotationProcessors=False): - if not includeLibs or not includeSelf: + """ + Add the transitive set of dependencies for this library to the 'deps' list. + """ + if not includeLibs: + return deps + childDeps = list(self.deps) + if self in deps: return deps - deps.append(self) + for name in childDeps: + assert name != self.name + dep = library(name) + if not dep in deps: + dep.all_deps(deps, includeLibs=includeLibs, includeAnnotationProcessors=includeAnnotationProcessors) + if not self in deps and includeSelf: + deps.append(self) return deps class HgConfig: @@ -619,7 +728,8 @@ sourcePath = attrs.pop('sourcePath', None) sourceUrls = pop_list(attrs, 'sourceUrls') sourceSha1 = attrs.pop('sourceSha1', None) - l = Library(self, name, path, mustExist, urls, sha1, sourcePath, sourceUrls, sourceSha1) + deps = pop_list(attrs, 'dependencies') + l = Library(self, name, path, mustExist, urls, sha1, sourcePath, sourceUrls, sourceSha1, deps) l.__dict__.update(attrs) self.libs.append(l) @@ -1690,10 +1800,13 @@ parser.add_argument('--only', action='store', help='comma separated projects to build, without checking their dependencies (omit to build all projects)') parser.add_argument('--no-java', action='store_false', dest='java', help='do not build Java projects') parser.add_argument('--no-native', action='store_false', dest='native', help='do not build native projects') - parser.add_argument('--force-javac', action='store_true', dest='javac', help='use javac despite ecj.jar is found or not') - parser.add_argument('--jdt', help='path to ecj.jar, the Eclipse batch compiler (default: ' + defaultEcjPath + ')', default=defaultEcjPath, metavar='') parser.add_argument('--jdt-warning-as-error', action='store_true', help='convert all Eclipse batch compiler warnings to errors') - parser.add_argument('--error-prone', dest='error_prone', help='path to error-prone.jar', metavar='') + parser.add_argument('--jdt-show-task-tags', action='store_true', help='show task tags as Eclipse batch compiler warnings') + compilerSelect = parser.add_mutually_exclusive_group() + compilerSelect.add_argument('--error-prone', dest='error_prone', help='path to error-prone.jar', metavar='') + compilerSelect.add_argument('--jdt', help='path to ecj.jar, the Eclipse batch compiler (default: ' + defaultEcjPath + ')', default=defaultEcjPath, metavar='') + compilerSelect.add_argument('--force-javac', action='store_true', dest='javac', help='use javac despite ecj.jar is found or not') + if suppliedParser: parser.add_argument('remainder', nargs=REMAINDER, metavar='...') @@ -1775,12 +1888,11 @@ cp = classpath(p.name, includeSelf=True) sourceDirs = p.source_dirs() - mustBuild = args.force - if not mustBuild: + buildReason = 'forced build' if args.force else None + if not buildReason: for dep in p.all_deps([], False): if dep.name in built: - mustBuild = True - + buildReason = dep.name + ' rebuilt' jasminAvailable = None javafilelist = [] @@ -1829,20 +1941,19 @@ if exists(dirname(dst)) and (not exists(dst) or os.path.getmtime(dst) < os.path.getmtime(src)): shutil.copyfile(src, dst) - if not mustBuild: + if not buildReason: for javafile in javafiles: classfile = TimeStampFile(outputDir + javafile[len(sourceDir):-len('java')] + 'class') if not classfile.exists() or classfile.isOlderThan(javafile): - mustBuild = True + buildReason = 'class file(s) out of date' break aps = p.annotation_processors() apsOutOfDate = p.update_current_annotation_processors_file() if apsOutOfDate: - logv('[annotation processors for {0} changed]'.format(p.name)) - mustBuild = True - - if not mustBuild: + buildReason = 'annotation processor(s) changed' + + if not buildReason: logv('[all class files for {0} are up to date - skipping]'.format(p.name)) continue @@ -1874,10 +1985,14 @@ toBeDeleted = [argfileName] try: + + def logCompilation(p, compiler, reason): + log('Compiling Java sources for {} with {}... [{}]'.format(p.name, compiler, reason)) + if not jdtJar: mainJava = java() if not args.error_prone: - log('Compiling Java sources for {0} with javac...'.format(p.name)) + logCompilation(p, 'javac', buildReason) javacCmd = [mainJava.javac, '-g', '-J-Xmx1g', '-source', compliance, '-target', compliance, '-classpath', cp, '-d', outputDir, '-bootclasspath', jdk.bootclasspath(), '-endorseddirs', jdk.endorseddirs(), '-extdirs', jdk.extdirs()] if jdk.debug_port is not None: javacCmd += ['-J-Xdebug', '-J-Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=' + str(jdk.debug_port)] @@ -1888,7 +2003,7 @@ javacCmd.append('-XDignore.symbol.file') run(javacCmd) else: - log('Compiling Java sources for {0} with javac (with error-prone)...'.format(p.name)) + logCompilation(p, 'javac (with error-prone)', buildReason) javaArgs = ['-Xmx1g'] javacArgs = ['-g', '-source', compliance, '-target', compliance, '-classpath', cp, '-d', outputDir, '-bootclasspath', jdk.bootclasspath(), '-endorseddirs', jdk.endorseddirs(), '-extdirs', jdk.extdirs()] javacArgs += processorArgs @@ -1897,7 +2012,7 @@ javacArgs.append('-XDignore.symbol.file') run_java(javaArgs + ['-cp', os.pathsep.join([mainJava.toolsjar, args.error_prone]), 'com.google.errorprone.ErrorProneCompiler'] + javacArgs) else: - log('Compiling Java sources for {0} with JDT...'.format(p.name)) + logCompilation(p, 'JDT', buildReason) jdtVmArgs = ['-Xmx1g', '-jar', jdtJar] @@ -1918,11 +2033,15 @@ if not exists(jdtProperties): log('JDT properties file {0} not found'.format(jdtProperties)) else: - # convert all warnings to errors - if args.jdt_warning_as_error: + with open(jdtProperties) as fp: + origContent = fp.read() + content = origContent + if args.jdt_warning_as_error: + content = content.replace('=warning', '=error') + if not args.jdt_show_task_tags: + content = content + '\norg.eclipse.jdt.core.compiler.problem.tasks=ignore' + if origContent != content: jdtPropertiesTmp = jdtProperties + '.tmp' - with open(jdtProperties) as fp: - content = fp.read().replace('=warning', '=error') with open(jdtPropertiesTmp, 'w') as fp: fp.write(content) toBeDeleted.append(jdtPropertiesTmp) @@ -1943,6 +2062,39 @@ return args return None +def _chunk_files_for_command_line(files, limit=None, pathFunction=None): + """ + Returns a generator for splitting up a list of files into chunks such that the + size of the space separated file paths in a chunk is less than a given limit. + This is used to work around system command line length limits. + """ + chunkSize = 0 + chunkStart = 0 + if limit is None: + commandLinePrefixAllowance = 3000 + if get_os() == 'windows': + # The CreateProcess function on Windows limits the length of a command line to + # 32,768 characters (http://msdn.microsoft.com/en-us/library/ms682425%28VS.85%29.aspx) + limit = 32768 - commandLinePrefixAllowance + else: + # Using just SC_ARG_MAX without extra downwards adjustment + # results in "[Errno 7] Argument list too long" on MacOS. + syslimit = os.sysconf('SC_ARG_MAX') - 20000 + limit = syslimit - commandLinePrefixAllowance + for i in range(len(files)): + path = files[i] if pathFunction is None else pathFunction(files[i]) + size = len(path) + 1 + if chunkSize + size < limit: + chunkSize += size + else: + assert i > chunkStart + yield files[chunkStart:i] + chunkStart = i + chunkSize = 0 + if chunkStart == 0: + assert chunkSize < limit + yield files + def eclipseformat(args): """run the Eclipse Code Formatter on the Java sources @@ -2045,18 +2197,19 @@ if res is not batch: res.javafiles = res.javafiles + batch.javafiles - print "we have: " + str(len(batches)) + " batches" + log("we have: " + str(len(batches)) + " batches") for batch in batches.itervalues(): - run([args.eclipse_exe, - '-nosplash', - '-application', - 'org.eclipse.jdt.core.JavaCodeFormatter', - '-vm', java(batch.javaCompliance).java, - '-config', batch.path] - + [f.path for f in batch.javafiles]) - for fi in batch.javafiles: - if fi.update(batch.removeTrailingWhitespace): - modified.append(fi) + for chunk in _chunk_files_for_command_line(batch.javafiles, pathFunction=lambda f: f.path): + run([args.eclipse_exe, + '-nosplash', + '-application', + 'org.eclipse.jdt.core.JavaCodeFormatter', + '-vm', java(batch.javaCompliance).java, + '-config', batch.path] + + [f.path for f in chunk]) + for fi in chunk: + if fi.update(batch.removeTrailingWhitespace): + modified.append(fi) log('{0} files were modified'.format(len(modified))) @@ -2165,124 +2318,50 @@ log('Running pylint on ' + pyfile + '...') run(['pylint', '--reports=n', '--rcfile=' + rcfile, pyfile], env=env) +""" +Utility for creating and updating a zip file atomically. +""" +class Archiver: + def __init__(self, path): + self.path = path + + def __enter__(self): + if self.path: + fd, tmp = tempfile.mkstemp(suffix='', prefix=basename(self.path) + '.', dir=dirname(self.path)) + self.tmpFd = fd + self.tmpPath = tmp + self.zf = zipfile.ZipFile(tmp, 'w') + else: + self.tmpFd = None + self.tmpPath = None + self.zf = None + return self + + def __exit__(self, exc_type, exc_value, traceback): + if self.zf: + self.zf.close() + os.close(self.tmpFd) + # Correct the permissions on the temporary file which is created with restrictive permissions + os.chmod(self.tmpPath, 0o666 & ~currentUmask) + # Atomic on Unix + shutil.move(self.tmpPath, self.path) + def archive(args): """create jar files for projects and distributions""" parser = ArgumentParser(prog='mx archive') parser.add_argument('names', nargs=REMAINDER, metavar='[|@]...') args = parser.parse_args(args) - - class Archive: - def __init__(self, path): - self.path = path - - def __enter__(self): - if self.path: - fd, tmp = tempfile.mkstemp(suffix='', prefix=basename(self.path) + '.', dir=dirname(self.path)) - self.tmpFd = fd - self.tmpPath = tmp - self.zf = zipfile.ZipFile(tmp, 'w') - else: - self.tmpFd = None - self.tmpPath = None - self.zf = None - return self - - def __exit__(self, exc_type, exc_value, traceback): - if self.zf: - self.zf.close() - os.close(self.tmpFd) - # Correct the permissions on the temporary file which is created with restrictive permissions - os.chmod(self.tmpPath, 0o666 & ~currentUmask) - # Atomic on Unix - shutil.move(self.tmpPath, self.path) - archives = [] for name in args.names: if name.startswith('@'): dname = name[1:] d = distribution(dname) - with Archive(d.path) as arc, Archive(d.sourcesPath) as srcArc: - services = {} - def overwriteCheck(zf, arcname, source): - if arcname in zf.namelist(): - log('warning: ' + d.path + ': overwriting ' + arcname + ' [source: ' + source + ']') - - for dep in d.sorted_deps(includeLibs=True): - if dep.isLibrary(): - l = dep - # merge library jar into distribution jar - logv('[' + d.path + ': adding library ' + l.name + ']') - lpath = l.get_path(resolve=True) - libSourcePath = l.get_source_path(resolve=True) - if lpath: - with zipfile.ZipFile(lpath, 'r') as lp: - for arcname in lp.namelist(): - if arcname.startswith('META-INF/services/') and not arcname == 'META-INF/services/': - service = arcname[len('META-INF/services/'):] - assert '/' not in service - services.setdefault(service, []).extend(lp.read(arcname).splitlines()) - else: - overwriteCheck(arc.zf, arcname, lpath + '!' + arcname) - arc.zf.writestr(arcname, lp.read(arcname)) - if srcArc.zf and libSourcePath: - with zipfile.ZipFile(libSourcePath, 'r') as lp: - for arcname in lp.namelist(): - overwriteCheck(srcArc.zf, arcname, lpath + '!' + arcname) - srcArc.zf.writestr(arcname, lp.read(arcname)) - else: - p = dep - # skip a Java project if its Java compliance level is "higher" than the configured JDK - jdk = java(p.javaCompliance) - if not jdk: - log('Excluding {0} from {2} (Java compliance level {1} required)'.format(p.name, p.javaCompliance, d.path)) - continue - - logv('[' + d.path + ': adding project ' + p.name + ']') - outputDir = p.output_dir() - for root, _, files in os.walk(outputDir): - relpath = root[len(outputDir) + 1:] - if relpath == join('META-INF', 'services'): - for service in files: - with open(join(root, service), 'r') as fp: - services.setdefault(service, []).extend([provider.strip() for provider in fp.readlines()]) - elif relpath == join('META-INF', 'providers'): - for provider in files: - with open(join(root, provider), 'r') as fp: - for service in fp: - services.setdefault(service.strip(), []).append(provider) - else: - for f in files: - arcname = join(relpath, f).replace(os.sep, '/') - overwriteCheck(arc.zf, arcname, join(root, f)) - arc.zf.write(join(root, f), arcname) - if srcArc.zf: - for srcDir in p.source_dirs(): - for root, _, files in os.walk(srcDir): - relpath = root[len(srcDir) + 1:] - for f in files: - if f.endswith('.java'): - arcname = join(relpath, f).replace(os.sep, '/') - overwriteCheck(srcArc.zf, arcname, join(root, f)) - srcArc.zf.write(join(root, f), arcname) - - for service, providers in services.iteritems(): - arcname = 'META-INF/services/' + service - arc.zf.writestr(arcname, '\n'.join(providers)) - - d.notify_updated() + d.make_archive() archives.append(d.path) - else: p = project(name) - outputDir = p.output_dir() - with Archive(join(p.dir, p.name + '.jar')) as arc: - for root, _, files in os.walk(outputDir): - for f in files: - relpath = root[len(outputDir) + 1:] - arcname = join(relpath, f).replace(os.sep, '/') - arc.zf.write(join(root, f), arcname) - archives.append(arc.path) + archives.append(p.make_archive()) return archives @@ -2462,26 +2541,9 @@ log('Running Checkstyle on {0} using {1}...'.format(sourceDir, config)) try: - - # Checkstyle is unable to read the filenames to process from a file, and the - # CreateProcess function on Windows limits the length of a command line to - # 32,768 characters (http://msdn.microsoft.com/en-us/library/ms682425%28VS.85%29.aspx) - # so calling Checkstyle must be done in batches. - while len(javafilelist) != 0: - i = 0 - size = 0 - while i < len(javafilelist): - s = len(javafilelist[i]) + 1 - if size + s < 30000: - size += s - i += 1 - else: - break - - batch = javafilelist[:i] - javafilelist = javafilelist[i:] + for chunk in _chunk_files_for_command_line(javafilelist): try: - run_java(['-Xmx1g', '-jar', library('CHECKSTYLE').get_path(True), '-f', 'xml', '-c', config, '-o', auditfileName] + batch, nonZeroIsFatal=False) + run_java(['-Xmx1g', '-jar', library('CHECKSTYLE').get_path(True), '-f', 'xml', '-c', config, '-o', auditfileName] + chunk, nonZeroIsFatal=False) finally: if exists(auditfileName): errors = [] @@ -2853,35 +2915,47 @@ if exists(join(p.dir, 'plugin.xml')): # eclipse plugin project out.element('classpathentry', {'kind' : 'con', 'path' : 'org.eclipse.pde.core.requiredPlugins'}) + containerDeps = set() + libraryDeps = set() + projectDeps = set() + for dep in p.all_deps([], True): if dep == p: continue - if dep.isLibrary(): if hasattr(dep, 'eclipse.container'): - out.element('classpathentry', {'exported' : 'true', 'kind' : 'con', 'path' : getattr(dep, 'eclipse.container')}) - elif hasattr(dep, 'eclipse.project'): - out.element('classpathentry', {'combineaccessrules' : 'false', 'exported' : 'true', 'kind' : 'src', 'path' : '/' + getattr(dep, 'eclipse.project')}) + container = getattr(dep, 'eclipse.container') + containerDeps.add(container) + libraryDeps -= set(dep.all_deps([], True)) else: - path = dep.path - dep.get_path(resolve=True) - if not path or (not exists(path) and not dep.mustExist): - continue - - # Relative paths for "lib" class path entries have various semantics depending on the Eclipse - # version being used (e.g. see https://bugs.eclipse.org/bugs/show_bug.cgi?id=274737) so it's - # safest to simply use absolute paths. - path = _make_absolute(path, p.suite.dir) - - attributes = {'exported' : 'true', 'kind' : 'lib', 'path' : path} - - sourcePath = dep.get_source_path(resolve=True) - if sourcePath is not None: - attributes['sourcepath'] = sourcePath - out.element('classpathentry', attributes) - libFiles.append(path) + libraryDeps.add(dep) else: - out.element('classpathentry', {'combineaccessrules' : 'false', 'exported' : 'true', 'kind' : 'src', 'path' : '/' + dep.name}) + projectDeps.add(dep) + + for dep in containerDeps: + out.element('classpathentry', {'exported' : 'true', 'kind' : 'con', 'path' : dep}) + + for dep in libraryDeps: + path = dep.path + dep.get_path(resolve=True) + if not path or (not exists(path) and not dep.mustExist): + continue + + # Relative paths for "lib" class path entries have various semantics depending on the Eclipse + # version being used (e.g. see https://bugs.eclipse.org/bugs/show_bug.cgi?id=274737) so it's + # safest to simply use absolute paths. + path = _make_absolute(path, p.suite.dir) + + attributes = {'exported' : 'true', 'kind' : 'lib', 'path' : path} + + sourcePath = dep.get_source_path(resolve=True) + if sourcePath is not None: + attributes['sourcepath'] = sourcePath + out.element('classpathentry', attributes) + libFiles.append(path) + + for dep in projectDeps: + out.element('classpathentry', {'combineaccessrules' : 'false', 'exported' : 'true', 'kind' : 'src', 'path' : '/' + dep.name}) out.element('classpathentry', {'kind' : 'output', 'path' : getattr(p, 'eclipse.output', 'bin')}) out.close('classpath') @@ -3611,7 +3685,7 @@ moduleXml.open('module', attributes={'type': 'JAVA_MODULE', 'version': '4'}) moduleXml.open('component', attributes={'name': 'NewModuleRootManager', 'LANGUAGE_LEVEL': intellijLanguageLevel, 'inherit-compiler-output': 'false'}) - moduleXml.element('output', attributes={'url': 'file://$MODULE_DIR$/bin'}) # TODO use p.output_dir() ? + moduleXml.element('output', attributes={'url': 'file://$MODULE_DIR$/bin'}) moduleXml.element('exclude-output') moduleXml.open('content', attributes={'url': 'file://$MODULE_DIR$'}) @@ -3675,12 +3749,12 @@ libraryXml.open('component', attributes={'name': 'libraryTable'}) libraryXml.open('library', attributes={'name': library.name}) libraryXml.open('CLASSES') - libraryXml.element('root', attributes={'url': 'jar://$PROJECT_DIR$/' + os.path.relpath(library.path, suite.dir) + '!/'}) + libraryXml.element('root', attributes={'url': 'jar://$PROJECT_DIR$/' + os.path.relpath(library.get_path(True), suite.dir) + '!/'}) libraryXml.close('CLASSES') libraryXml.element('JAVADOC') if library.sourcePath: libraryXml.open('SOURCES') - libraryXml.element('root', attributes={'url': 'jar://$PROJECT_DIR$/' + os.path.relpath(library.sourcePath, suite.dir) + '!/'}) + libraryXml.element('root', attributes={'url': 'jar://$PROJECT_DIR$/' + os.path.relpath(library.get_source_path(True), suite.dir) + '!/'}) libraryXml.close('SOURCES') else: libraryXml.element('SOURCES') @@ -3732,7 +3806,7 @@ # Wite misc.xml for global JDK config miscXml = XMLDoc() miscXml.open('project', attributes={'version': '4'}) - miscXml.element('component', attributes={'name': 'ProjectRootManager', 'version': '2', 'languagelevel': _complianceToIntellijLanguageLevel(java().javaCompliance), 'project-jdk-name': str(java().javaCompliance), 'project-jdk-type': 'JavaSDK'}) + miscXml.element('component', attributes={'name': 'ProjectRootManager', 'version': '2', 'languageLevel': _complianceToIntellijLanguageLevel(java().javaCompliance), 'project-jdk-name': str(java().javaCompliance), 'project-jdk-type': 'JavaSDK'}) miscXml.close('project') miscFile = join(ideaProjectDirectory, 'misc.xml') update_file(miscFile, miscXml.xml(indent=' ', newl='\n')) @@ -3773,7 +3847,7 @@ def ideinit(args, refreshOnly=False, buildProcessorJars=True): - """(re)generate Eclipse and NetBeans project configurations""" + """(re)generate Eclipse, NetBeans and Intellij project configurations""" eclipseinit(args, refreshOnly=refreshOnly, buildProcessorJars=buildProcessorJars) netbeansinit(args, refreshOnly=refreshOnly, buildProcessorJars=buildProcessorJars) intellijinit(args, refreshOnly=refreshOnly) @@ -4270,6 +4344,111 @@ return items[indexes[0]] return None +def exportlibs(args): + """export libraries to an archive file""" + + parser = ArgumentParser(prog='exportlibs') + parser.add_argument('-b', '--base', action='store', help='base name of archive (default: libs)', default='libs', metavar='') + parser.add_argument('-a', '--include-all', action='store_true', help="include all defined libaries") + parser.add_argument('--arc', action='store', choices=['tgz', 'tbz2', 'tar', 'zip'], default='tgz', help='the type of the archive to create') + parser.add_argument('--no-sha1', action='store_false', dest='sha1', help='do not create SHA1 signature of archive') + parser.add_argument('--no-md5', action='store_false', dest='md5', help='do not create MD5 signature of archive') + parser.add_argument('--include-system-libs', action='store_true', help='include system libraries (i.e., those not downloaded from URLs)') + parser.add_argument('extras', nargs=REMAINDER, help='extra files and directories to add to archive', metavar='files...') + args = parser.parse_args(args) + + def createArchive(addMethod): + entries = {} + def add(path, arcname): + apath = os.path.abspath(path) + if not entries.has_key(arcname): + entries[arcname] = apath + logv('[adding ' + path + ']') + addMethod(path, arcname=arcname) + elif entries[arcname] != apath: + logv('[warning: ' + apath + ' collides with ' + entries[arcname] + ' as ' + arcname + ']') + else: + logv('[already added ' + path + ']') + + libsToExport = set() + if args.include_all: + for lib in _libs.itervalues(): + libsToExport.add(lib) + else: + def isValidLibrary(dep): + if dep in _libs.iterkeys(): + lib = _libs[dep] + if len(lib.urls) != 0 or args.include_system_libs: + return lib + return None + + # iterate over all project dependencies and find used libraries + for p in _projects.itervalues(): + for dep in p.deps: + r = isValidLibrary(dep) + if r: + libsToExport.add(r) + + # a library can have other libraries as dependency + size = 0 + while size != len(libsToExport): + size = len(libsToExport) + for lib in libsToExport.copy(): + for dep in lib.deps: + r = isValidLibrary(dep) + if r: + libsToExport.add(r) + + for lib in libsToExport: + add(lib.get_path(resolve=True), lib.path) + if lib.sha1: + add(lib.get_path(resolve=True) + ".sha1", lib.path + ".sha1") + if lib.sourcePath: + add(lib.get_source_path(resolve=True), lib.sourcePath) + if lib.sourceSha1: + add(lib.get_source_path(resolve=True) + ".sha1", lib.sourcePath + ".sha1") + + if args.extras: + for e in args.extras: + if os.path.isdir(e): + for root, _, filenames in os.walk(e): + for name in filenames: + f = join(root, name) + add(f, f) + else: + add(e, e) + + if args.arc == 'zip': + path = args.base + '.zip' + with zipfile.ZipFile(path, 'w') as zf: + createArchive(zf.write) + else: + path = args.base + '.tar' + mode = 'w' + if args.arc != 'tar': + sfx = args.arc[1:] + mode = mode + ':' + sfx + path = path + '.' + sfx + with tarfile.open(path, mode) as tar: + createArchive(tar.add) + log('created ' + path) + + def digest(enabled, path, factory, suffix): + if enabled: + d = factory() + with open(path, 'rb') as f: + while True: + buf = f.read(4096) + if not buf: + break + d.update(buf) + with open(path + '.' + suffix, 'w') as fp: + print >> fp, d.hexdigest() + log('created ' + path + '.' + suffix) + + digest(args.sha1, path, hashlib.sha1, 'sha1') + digest(args.md5, path, hashlib.md5, 'md5') + def javap(args): """disassemble classes matching given pattern with javap""" @@ -4338,6 +4517,7 @@ 'clean': [clean, ''], 'eclipseinit': [eclipseinit, ''], 'eclipseformat': [eclipseformat, ''], + 'exportlibs': [exportlibs, ''], 'findclass': [findclass, ''], 'fsckprojects': [fsckprojects, ''], 'help': [help_, '[command]'], diff -r 3dde8d8c95b8 -r 40d0022115ee src/cpu/sparc/vm/graalCodeInstaller_sparc.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/cpu/sparc/vm/graalCodeInstaller_sparc.cpp Mon Apr 28 11:18:15 2014 +0200 @@ -0,0 +1,146 @@ +/* + * Copyright (c) 2013, 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +#include "graal/graalCodeInstaller.hpp" +#include "graal/graalCompiler.hpp" +#include "graal/graalCompilerToVM.hpp" +#include "graal/graalJavaAccess.hpp" + +jint CodeInstaller::pd_next_offset(NativeInstruction* inst, jint pc_offset, oop method) { + if (inst->is_call() || inst->is_jump()) { + return pc_offset + NativeCall::instruction_size; + } else if (inst->is_call_reg()) { + return pc_offset + NativeCallReg::instruction_size; + } else if (inst->is_sethi()) { + return pc_offset + NativeFarCall::instruction_size; + } else { + fatal("unsupported type of instruction for call site"); + return 0; + } +} + +void CodeInstaller::pd_patch_OopData(int pc_offset, oop data) { + address pc = _instructions->start() + pc_offset; + Handle obj = OopData::object(data); + jobject value = JNIHandles::make_local(obj()); + if (OopData::compressed(data)) { + fatal("unimplemented: narrow oop relocation"); + } else { + NativeMovConstReg* move = nativeMovConstReg_at(pc); + move->set_data((intptr_t) value); + + // We need two relocations: one on the sethi and one on the add. + int oop_index = _oop_recorder->find_index(value); + RelocationHolder rspec = oop_Relocation::spec(oop_index); + _instructions->relocate(pc + NativeMovConstReg::sethi_offset, rspec); + _instructions->relocate(pc + NativeMovConstReg::add_offset, rspec); + } +} + +void CodeInstaller::pd_patch_DataSectionReference(int pc_offset, oop data) { + address pc = _instructions->start() + pc_offset; + jint offset = DataSectionReference::offset(data); + + NativeMovRegMem* load = nativeMovRegMem_at(pc); + int disp = _constants_size + pc_offset - offset - BytesPerInstWord; + load->set_offset(-disp); +} + +void CodeInstaller::pd_relocate_CodeBlob(CodeBlob* cb, NativeInstruction* inst) { + fatal("CodeInstaller::pd_relocate_CodeBlob - sparc unimp"); +} + +void CodeInstaller::pd_relocate_ForeignCall(NativeInstruction* inst, jlong foreign_call_destination) { + address pc = (address) inst; + if (inst->is_call()) { + NativeCall* call = nativeCall_at(pc); + call->set_destination((address) foreign_call_destination); + _instructions->relocate(call->instruction_address(), runtime_call_Relocation::spec()); + } else if (inst->is_sethi()) { + NativeJump* jump = nativeJump_at(pc); + jump->set_jump_destination((address) foreign_call_destination); + _instructions->relocate(jump->instruction_address(), runtime_call_Relocation::spec()); + } else { + fatal(err_msg("unknown call or jump instruction at %p", pc)); + } + TRACE_graal_3("relocating (foreign call) at %p", inst); +} + +void CodeInstaller::pd_relocate_JavaMethod(oop hotspot_method, jint pc_offset) { +#ifdef ASSERT + Method* method = NULL; + // we need to check, this might also be an unresolved method + if (hotspot_method->is_a(HotSpotResolvedJavaMethod::klass())) { + method = getMethodFromHotSpotMethod(hotspot_method); + } +#endif + switch (_next_call_type) { + case INLINE_INVOKE: + break; + case INVOKEVIRTUAL: + case INVOKEINTERFACE: { + assert(method == NULL || !method->is_static(), "cannot call static method with invokeinterface"); + NativeCall* call = nativeCall_at(_instructions->start() + pc_offset); + call->set_destination(SharedRuntime::get_resolve_virtual_call_stub()); + _instructions->relocate(call->instruction_address(), virtual_call_Relocation::spec(_invoke_mark_pc)); + break; + } + case INVOKESTATIC: { + assert(method == NULL || method->is_static(), "cannot call non-static method with invokestatic"); + NativeCall* call = nativeCall_at(_instructions->start() + pc_offset); + call->set_destination(SharedRuntime::get_resolve_static_call_stub()); + _instructions->relocate(call->instruction_address(), relocInfo::static_call_type); + break; + } + case INVOKESPECIAL: { + assert(method == NULL || !method->is_static(), "cannot call static method with invokespecial"); + NativeCall* call = nativeCall_at(_instructions->start() + pc_offset); + call->set_destination(SharedRuntime::get_resolve_opt_virtual_call_stub()); + _instructions->relocate(call->instruction_address(), relocInfo::opt_virtual_call_type); + break; + } + default: + fatal("invalid _next_call_type value"); + break; + } +} + +void CodeInstaller::pd_relocate_poll(address pc, jint mark) { + switch (mark) { + case POLL_NEAR: + fatal("unimplemented"); + break; + case POLL_FAR: + _instructions->relocate(pc, relocInfo::poll_type); + break; + case POLL_RETURN_NEAR: + fatal("unimplemented"); + break; + case POLL_RETURN_FAR: + _instructions->relocate(pc, relocInfo::poll_return_type); + break; + default: + fatal("invalid mark value"); + break; + } +} diff -r 3dde8d8c95b8 -r 40d0022115ee src/cpu/sparc/vm/graalCodeInstaller_sparc.hpp --- a/src/cpu/sparc/vm/graalCodeInstaller_sparc.hpp Fri Apr 25 16:21:07 2014 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,151 +0,0 @@ -/* - * 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. - */ - -#ifndef CPU_SPARC_VM_CODEINSTALLER_SPARC_HPP -#define CPU_SPARC_VM_CODEINSTALLER_SPARC_HPP - -#include "graal/graalCompiler.hpp" -#include "graal/graalCompilerToVM.hpp" -#include "graal/graalJavaAccess.hpp" - -inline jint CodeInstaller::pd_next_offset(NativeInstruction* inst, jint pc_offset, oop method) { - if (inst->is_call() || inst->is_jump()) { - return pc_offset + NativeCall::instruction_size; - } else if (inst->is_call_reg()) { - return pc_offset + NativeCallReg::instruction_size; - } else if (inst->is_sethi()) { - return pc_offset + NativeFarCall::instruction_size; - } else { - fatal("unsupported type of instruction for call site"); - return 0; - } -} - -inline void CodeInstaller::pd_patch_OopData(int pc_offset, oop data) { - if (OopData::compressed(obj)) { - fatal("unimplemented: narrow oop relocation"); - } else { - address pc = _instructions->start() + pc_offset; - Handle obj = OopData::object(data); - jobject value = JNIHandles::make_local(obj()); - - NativeMovConstReg* move = nativeMovConstReg_at(pc); - move->set_data((intptr_t) value); - - // We need two relocations: one on the sethi and one on the add. - int oop_index = _oop_recorder->find_index(value); - RelocationHolder rspec = oop_Relocation::spec(oop_index); - _instructions->relocate(pc + NativeMovConstReg::sethi_offset, rspec); - _instructions->relocate(pc + NativeMovConstReg::add_offset, rspec); - } -} - -inline void CodeInstaller::pd_patch_DataSectionReference(int pc_offset, oop data) { - address pc = _instructions->start() + pc_offset; - jint offset = DataSectionReference::offset(data); - - NativeMovRegMem* load = nativeMovRegMem_at(pc); - int disp = _constants_size + pc_offset - offset - BytesPerInstWord; - load->set_offset(-disp); -} - -inline void CodeInstaller::pd_relocate_CodeBlob(CodeBlob* cb, NativeInstruction* inst) { - fatal("CodeInstaller::pd_relocate_CodeBlob - sparc unimp"); -} - -inline void CodeInstaller::pd_relocate_ForeignCall(NativeInstruction* inst, jlong foreign_call_destination) { - address pc = (address) inst; - if (inst->is_call()) { - NativeCall* call = nativeCall_at(pc); - call->set_destination((address) foreign_call_destination); - _instructions->relocate(call->instruction_address(), runtime_call_Relocation::spec()); - } else if (inst->is_sethi()) { - NativeJump* jump = nativeJump_at(pc); - jump->set_jump_destination((address) foreign_call_destination); - _instructions->relocate(jump->instruction_address(), runtime_call_Relocation::spec()); - } else { - fatal(err_msg("unknown call or jump instruction at %p", pc)); - } - TRACE_graal_3("relocating (foreign call) at %p", inst); -} - -inline void CodeInstaller::pd_relocate_JavaMethod(oop hotspot_method, jint pc_offset) { -#ifdef ASSERT - Method* method = NULL; - // we need to check, this might also be an unresolved method - if (hotspot_method->is_a(HotSpotResolvedJavaMethod::klass())) { - method = getMethodFromHotSpotMethod(hotspot_method); - } -#endif - switch (_next_call_type) { - case INLINE_INVOKE: - break; - case INVOKEVIRTUAL: - case INVOKEINTERFACE: { - assert(method == NULL || !method->is_static(), "cannot call static method with invokeinterface"); - NativeCall* call = nativeCall_at(_instructions->start() + pc_offset); - call->set_destination(SharedRuntime::get_resolve_virtual_call_stub()); - _instructions->relocate(call->instruction_address(), virtual_call_Relocation::spec(_invoke_mark_pc)); - break; - } - case INVOKESTATIC: { - assert(method == NULL || method->is_static(), "cannot call non-static method with invokestatic"); - NativeCall* call = nativeCall_at(_instructions->start() + pc_offset); - call->set_destination(SharedRuntime::get_resolve_static_call_stub()); - _instructions->relocate(call->instruction_address(), relocInfo::static_call_type); - break; - } - case INVOKESPECIAL: { - assert(method == NULL || !method->is_static(), "cannot call static method with invokespecial"); - NativeCall* call = nativeCall_at(_instructions->start() + pc_offset); - call->set_destination(SharedRuntime::get_resolve_opt_virtual_call_stub()); - _instructions->relocate(call->instruction_address(), relocInfo::opt_virtual_call_type); - break; - } - default: - fatal("invalid _next_call_type value"); - break; - } -} - -inline void CodeInstaller::pd_relocate_poll(address pc, jint mark) { - switch (mark) { - case POLL_NEAR: { - fatal("unimplemented"); - } - case POLL_FAR: - _instructions->relocate(pc, relocInfo::poll_type); - break; - case POLL_RETURN_NEAR: { - fatal("unimplemented"); - } - case POLL_RETURN_FAR: - _instructions->relocate(pc, relocInfo::poll_return_type); - break; - default: - fatal("invalid mark value"); - break; - } -} - -#endif // CPU_SPARC_VM_CODEINSTALLER_SPARC_HPP diff -r 3dde8d8c95b8 -r 40d0022115ee src/cpu/x86/vm/graalCodeInstaller_x86.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/cpu/x86/vm/graalCodeInstaller_x86.cpp Mon Apr 28 11:18:15 2014 +0200 @@ -0,0 +1,212 @@ +/* + * Copyright (c) 2013, 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +#include "precompiled.hpp" +#include "compiler/disassembler.hpp" +#include "runtime/javaCalls.hpp" +#include "graal/graalEnv.hpp" +#include "graal/graalCompiler.hpp" +#include "graal/graalCodeInstaller.hpp" +#include "graal/graalJavaAccess.hpp" +#include "graal/graalCompilerToVM.hpp" +#include "graal/graalRuntime.hpp" +#include "asm/register.hpp" +#include "classfile/vmSymbols.hpp" +#include "code/vmreg.hpp" + +jint CodeInstaller::pd_next_offset(NativeInstruction* inst, jint pc_offset, oop method) { + if (inst->is_call() || inst->is_jump()) { + assert(NativeCall::instruction_size == (int)NativeJump::instruction_size, "unexpected size"); + return (pc_offset + NativeCall::instruction_size); + } else if (inst->is_mov_literal64()) { + // mov+call instruction pair + jint offset = pc_offset + NativeMovConstReg::instruction_size; + u_char* call = (u_char*) (_instructions->start() + offset); + assert((call[0] == 0x40 || call[0] == 0x41) && call[1] == 0xFF, "expected call with rex/rexb prefix byte"); + offset += 3; /* prefix byte + opcode byte + modrm byte */ + return (offset); + } else if (inst->is_call_reg()) { + // the inlined vtable stub contains a "call register" instruction + assert(method != NULL, "only valid for virtual calls"); + return (pc_offset + ((NativeCallReg *) inst)->next_instruction_offset()); + } else if (inst->is_cond_jump()) { + address pc = (address) (inst); + return pc_offset + (jint) (Assembler::locate_next_instruction(pc) - pc); + } else { + fatal("unsupported type of instruction for call site"); + return 0; + } +} + +void CodeInstaller::pd_patch_OopData(int pc_offset, oop data) { + address pc = _instructions->start() + pc_offset; + Handle obj = OopData::object(data); + jobject value = JNIHandles::make_local(obj()); + if (OopData::compressed(data)) { + address operand = Assembler::locate_operand(pc, Assembler::narrow_oop_operand); + int oop_index = _oop_recorder->find_index(value); + _instructions->relocate(pc, oop_Relocation::spec(oop_index), Assembler::narrow_oop_operand); + TRACE_graal_3("relocating (narrow oop constant) at %p/%p", pc, operand); + } else { + address operand = Assembler::locate_operand(pc, Assembler::imm_operand); + *((jobject*) operand) = value; + _instructions->relocate(pc, oop_Relocation::spec_for_immediate(), Assembler::imm_operand); + TRACE_graal_3("relocating (oop constant) at %p/%p", pc, operand); + } +} + +void CodeInstaller::pd_patch_DataSectionReference(int pc_offset, oop data) { + address pc = _instructions->start() + pc_offset; + jint offset = DataSectionReference::offset(data); + + address operand = Assembler::locate_operand(pc, Assembler::disp32_operand); + address next_instruction = Assembler::locate_next_instruction(pc); + address dest = _constants->start() + offset; + + long disp = dest - next_instruction; + assert(disp == (jint) disp, "disp doesn't fit in 32 bits"); + *((jint*) operand) = (jint) disp; + + _instructions->relocate(pc, section_word_Relocation::spec((address) dest, CodeBuffer::SECT_CONSTS), Assembler::disp32_operand); + TRACE_graal_3("relocating at %p/%p with destination at %p (%d)", pc, operand, dest, offset); +} + +void CodeInstaller::pd_relocate_CodeBlob(CodeBlob* cb, NativeInstruction* inst) { + if (cb->is_nmethod()) { + nmethod* nm = (nmethod*) cb; + nativeJump_at((address)inst)->set_jump_destination(nm->verified_entry_point()); + } else { + nativeJump_at((address)inst)->set_jump_destination(cb->code_begin()); + } + _instructions->relocate((address)inst, runtime_call_Relocation::spec(), Assembler::call32_operand); +} + +void CodeInstaller::pd_relocate_ForeignCall(NativeInstruction* inst, jlong foreign_call_destination) { + address pc = (address) inst; + if (inst->is_call()) { + // NOTE: for call without a mov, the offset must fit a 32-bit immediate + // see also CompilerToVM.getMaxCallTargetOffset() + NativeCall* call = nativeCall_at(pc); + call->set_destination((address) foreign_call_destination); + _instructions->relocate(call->instruction_address(), runtime_call_Relocation::spec(), Assembler::call32_operand); + } else if (inst->is_mov_literal64()) { + NativeMovConstReg* mov = nativeMovConstReg_at(pc); + mov->set_data((intptr_t) foreign_call_destination); + _instructions->relocate(mov->instruction_address(), runtime_call_Relocation::spec(), Assembler::imm_operand); + } else if (inst->is_jump()) { + NativeJump* jump = nativeJump_at(pc); + jump->set_jump_destination((address) foreign_call_destination); + _instructions->relocate(jump->instruction_address(), runtime_call_Relocation::spec(), Assembler::call32_operand); + } else if (inst->is_cond_jump()) { + address old_dest = nativeGeneralJump_at(pc)->jump_destination(); + address disp = Assembler::locate_operand(pc, Assembler::call32_operand); + *(jint*) disp += ((address) foreign_call_destination) - old_dest; + _instructions->relocate(pc, runtime_call_Relocation::spec(), Assembler::call32_operand); + } else { + fatal("unsupported relocation for foreign call"); + } + + TRACE_graal_3("relocating (foreign call) at %p", inst); +} + +void CodeInstaller::pd_relocate_JavaMethod(oop hotspot_method, jint pc_offset) { +#ifdef ASSERT + Method* method = NULL; + // we need to check, this might also be an unresolved method + if (hotspot_method->is_a(HotSpotResolvedJavaMethod::klass())) { + method = getMethodFromHotSpotMethod(hotspot_method); + } +#endif + switch (_next_call_type) { + case INLINE_INVOKE: + break; + case INVOKEVIRTUAL: + case INVOKEINTERFACE: { + assert(method == NULL || !method->is_static(), "cannot call static method with invokeinterface"); + + NativeCall* call = nativeCall_at(_instructions->start() + pc_offset); + call->set_destination(SharedRuntime::get_resolve_virtual_call_stub()); + _instructions->relocate(call->instruction_address(), + virtual_call_Relocation::spec(_invoke_mark_pc), + Assembler::call32_operand); + break; + } + case INVOKESTATIC: { + assert(method == NULL || method->is_static(), "cannot call non-static method with invokestatic"); + + NativeCall* call = nativeCall_at(_instructions->start() + pc_offset); + call->set_destination(SharedRuntime::get_resolve_static_call_stub()); + _instructions->relocate(call->instruction_address(), + relocInfo::static_call_type, Assembler::call32_operand); + break; + } + case INVOKESPECIAL: { + assert(method == NULL || !method->is_static(), "cannot call static method with invokespecial"); + NativeCall* call = nativeCall_at(_instructions->start() + pc_offset); + call->set_destination(SharedRuntime::get_resolve_opt_virtual_call_stub()); + _instructions->relocate(call->instruction_address(), + relocInfo::opt_virtual_call_type, Assembler::call32_operand); + break; + } + default: + break; + } +} + +static void relocate_poll_near(address pc) { + NativeInstruction* ni = nativeInstruction_at(pc); + int32_t* disp = (int32_t*) Assembler::locate_operand(pc, Assembler::disp32_operand); + int32_t offset = *disp; // The Java code installed the polling page offset into the disp32 operand + intptr_t new_disp = (intptr_t) (os::get_polling_page() + offset) - (intptr_t) ni; + *disp = (int32_t)new_disp; +} + + +void CodeInstaller::pd_relocate_poll(address pc, jint mark) { + switch (mark) { + case POLL_NEAR: { + relocate_poll_near(pc); + _instructions->relocate(pc, relocInfo::poll_type, Assembler::disp32_operand); + break; + } + case POLL_FAR: + // This is a load from a register so there is no relocatable operand. + // We just have to ensure that the format is not disp32_operand + // so that poll_Relocation::fix_relocation_after_move does the right + // thing (i.e. ignores this relocation record) + _instructions->relocate(pc, relocInfo::poll_type, Assembler::imm_operand); + break; + case POLL_RETURN_NEAR: { + relocate_poll_near(pc); + _instructions->relocate(pc, relocInfo::poll_return_type, Assembler::disp32_operand); + break; + } + case POLL_RETURN_FAR: + // see comment above for POLL_FAR + _instructions->relocate(pc, relocInfo::poll_return_type, Assembler::imm_operand); + break; + default: + fatal("invalid mark value"); + break; + } +} diff -r 3dde8d8c95b8 -r 40d0022115ee src/cpu/x86/vm/graalCodeInstaller_x86.hpp --- a/src/cpu/x86/vm/graalCodeInstaller_x86.hpp Fri Apr 25 16:21:07 2014 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,228 +0,0 @@ -/* - * 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. - */ -#ifndef CPU_X86_VM_CODEINSTALLER_X86_HPP -#define CPU_X86_VM_CODEINSTALLER_X86_HPP - -#include "compiler/disassembler.hpp" -#include "runtime/javaCalls.hpp" -#include "graal/graalEnv.hpp" -#include "graal/graalCompiler.hpp" -#include "graal/graalCodeInstaller.hpp" -#include "graal/graalJavaAccess.hpp" -#include "graal/graalCompilerToVM.hpp" -#include "graal/graalRuntime.hpp" -#include "asm/register.hpp" -#include "classfile/vmSymbols.hpp" -#include "code/vmreg.hpp" - -inline jint CodeInstaller::pd_next_offset(NativeInstruction* inst, jint pc_offset, oop method) { - if (inst->is_call() || inst->is_jump()) { - assert(NativeCall::instruction_size == (int)NativeJump::instruction_size, "unexpected size"); - return (pc_offset + NativeCall::instruction_size); - } else if (inst->is_mov_literal64()) { - // mov+call instruction pair - jint offset = pc_offset + NativeMovConstReg::instruction_size; - u_char* call = (u_char*) (_instructions->start() + offset); - assert((call[0] == 0x40 || call[0] == 0x41) && call[1] == 0xFF, "expected call with rex/rexb prefix byte"); - offset += 3; /* prefix byte + opcode byte + modrm byte */ - return (offset); - } else if (inst->is_call_reg()) { - // the inlined vtable stub contains a "call register" instruction - assert(method != NULL, "only valid for virtual calls"); - return (pc_offset + ((NativeCallReg *) inst)->next_instruction_offset()); - } else if (inst->is_cond_jump()) { - address pc = (address) (inst); - return pc_offset + (jint) (Assembler::locate_next_instruction(pc) - pc); - } else { - fatal("unsupported type of instruction for call site"); - return 0; - } -} - -inline bool check_metaspace_data(address pc, oop data) { - jlong value = MetaspaceData::value(data); - address operand = Assembler::locate_operand(pc, Assembler::imm_operand); - if (MetaspaceData::compressed(data)) { - assert(*((jint*) operand) == value, err_msg("wrong compressed metaspace pointer: %p != %p", *((jint*) operand), value)); - } else { - assert(*((jlong*) operand) == value, err_msg("wrong metaspace pointer: %p != %p", *((jlong*) operand), value)); - } - return true; -} - -inline void CodeInstaller::pd_patch_OopData(int pc_offset, oop data) { - address pc = _instructions->start() + pc_offset; - - Handle obj = OopData::object(data); - jobject value = JNIHandles::make_local(obj()); - if (OopData::compressed(data)) { - address operand = Assembler::locate_operand(pc, Assembler::narrow_oop_operand); - int oop_index = _oop_recorder->find_index(value); - _instructions->relocate(pc, oop_Relocation::spec(oop_index), Assembler::narrow_oop_operand); - TRACE_graal_3("relocating (narrow oop constant) at %p/%p", pc, operand); - } else { - address operand = Assembler::locate_operand(pc, Assembler::imm_operand); - *((jobject*) operand) = value; - _instructions->relocate(pc, oop_Relocation::spec_for_immediate(), Assembler::imm_operand); - TRACE_graal_3("relocating (oop constant) at %p/%p", pc, operand); - } -} - -inline void CodeInstaller::pd_patch_DataSectionReference(int pc_offset, oop data) { - address pc = _instructions->start() + pc_offset; - jint offset = DataSectionReference::offset(data); - - address operand = Assembler::locate_operand(pc, Assembler::disp32_operand); - address next_instruction = Assembler::locate_next_instruction(pc); - address dest = _constants->start() + offset; - - long disp = dest - next_instruction; - assert(disp == (jint) disp, "disp doesn't fit in 32 bits"); - *((jint*) operand) = (jint) disp; - - _instructions->relocate(pc, section_word_Relocation::spec((address) dest, CodeBuffer::SECT_CONSTS), Assembler::disp32_operand); - TRACE_graal_3("relocating at %p/%p with destination at %p (%d)", pc, operand, dest, offset); -} - -inline void CodeInstaller::pd_relocate_CodeBlob(CodeBlob* cb, NativeInstruction* inst) { - if (cb->is_nmethod()) { - nmethod* nm = (nmethod*) cb; - nativeJump_at((address)inst)->set_jump_destination(nm->verified_entry_point()); - } else { - nativeJump_at((address)inst)->set_jump_destination(cb->code_begin()); - } - _instructions->relocate((address)inst, runtime_call_Relocation::spec(), Assembler::call32_operand); -} - -inline void CodeInstaller::pd_relocate_ForeignCall(NativeInstruction* inst, jlong foreign_call_destination) { - address pc = (address) inst; - if (inst->is_call()) { - // NOTE: for call without a mov, the offset must fit a 32-bit immediate - // see also CompilerToVM.getMaxCallTargetOffset() - NativeCall* call = nativeCall_at(pc); - call->set_destination((address) foreign_call_destination); - _instructions->relocate(call->instruction_address(), runtime_call_Relocation::spec(), Assembler::call32_operand); - } else if (inst->is_mov_literal64()) { - NativeMovConstReg* mov = nativeMovConstReg_at(pc); - mov->set_data((intptr_t) foreign_call_destination); - _instructions->relocate(mov->instruction_address(), runtime_call_Relocation::spec(), Assembler::imm_operand); - } else if (inst->is_jump()) { - NativeJump* jump = nativeJump_at(pc); - jump->set_jump_destination((address) foreign_call_destination); - _instructions->relocate(jump->instruction_address(), runtime_call_Relocation::spec(), Assembler::call32_operand); - } else if (inst->is_cond_jump()) { - address old_dest = nativeGeneralJump_at(pc)->jump_destination(); - address disp = Assembler::locate_operand(pc, Assembler::call32_operand); - *(jint*) disp += ((address) foreign_call_destination) - old_dest; - _instructions->relocate(pc, runtime_call_Relocation::spec(), Assembler::call32_operand); - } else { - fatal("unsupported relocation for foreign call"); - } - - TRACE_graal_3("relocating (foreign call) at %p", inst); -} - -inline void CodeInstaller::pd_relocate_JavaMethod(oop hotspot_method, jint pc_offset) { -#ifdef ASSERT - Method* method = NULL; - // we need to check, this might also be an unresolved method - if (hotspot_method->is_a(HotSpotResolvedJavaMethod::klass())) { - method = getMethodFromHotSpotMethod(hotspot_method); - } -#endif - switch (_next_call_type) { - case INLINE_INVOKE: - break; - case INVOKEVIRTUAL: - case INVOKEINTERFACE: { - assert(method == NULL || !method->is_static(), "cannot call static method with invokeinterface"); - - NativeCall* call = nativeCall_at(_instructions->start() + pc_offset); - call->set_destination(SharedRuntime::get_resolve_virtual_call_stub()); - _instructions->relocate(call->instruction_address(), - virtual_call_Relocation::spec(_invoke_mark_pc), - Assembler::call32_operand); - break; - } - case INVOKESTATIC: { - assert(method == NULL || method->is_static(), "cannot call non-static method with invokestatic"); - - NativeCall* call = nativeCall_at(_instructions->start() + pc_offset); - call->set_destination(SharedRuntime::get_resolve_static_call_stub()); - _instructions->relocate(call->instruction_address(), - relocInfo::static_call_type, Assembler::call32_operand); - break; - } - case INVOKESPECIAL: { - assert(method == NULL || !method->is_static(), "cannot call static method with invokespecial"); - NativeCall* call = nativeCall_at(_instructions->start() + pc_offset); - call->set_destination(SharedRuntime::get_resolve_opt_virtual_call_stub()); - _instructions->relocate(call->instruction_address(), - relocInfo::opt_virtual_call_type, Assembler::call32_operand); - break; - } - default: - break; - } -} - -static void relocate_poll_near(address pc) { - NativeInstruction* ni = nativeInstruction_at(pc); - int32_t* disp = (int32_t*) Assembler::locate_operand(pc, Assembler::disp32_operand); - int32_t offset = *disp; // The Java code installed the polling page offset into the disp32 operand - intptr_t new_disp = (intptr_t) (os::get_polling_page() + offset) - (intptr_t) ni; - *disp = (int32_t)new_disp; -} - - -inline void CodeInstaller::pd_relocate_poll(address pc, jint mark) { - switch (mark) { - case POLL_NEAR: { - relocate_poll_near(pc); - _instructions->relocate(pc, relocInfo::poll_type, Assembler::disp32_operand); - break; - } - case POLL_FAR: - // This is a load from a register so there is no relocatable operand. - // We just have to ensure that the format is not disp32_operand - // so that poll_Relocation::fix_relocation_after_move does the right - // thing (i.e. ignores this relocation record) - _instructions->relocate(pc, relocInfo::poll_type, Assembler::imm_operand); - break; - case POLL_RETURN_NEAR: { - relocate_poll_near(pc); - _instructions->relocate(pc, relocInfo::poll_return_type, Assembler::disp32_operand); - break; - } - case POLL_RETURN_FAR: - // see comment above for MARK_POLL_FAR - _instructions->relocate(pc, relocInfo::poll_return_type, Assembler::imm_operand); - break; - default: - fatal("invalid mark value"); - break; - } -} - -#endif // CPU_X86_VM_CODEINSTALLER_X86_HPP - diff -r 3dde8d8c95b8 -r 40d0022115ee src/cpu/x86/vm/sharedRuntime_x86_64.cpp --- a/src/cpu/x86/vm/sharedRuntime_x86_64.cpp Fri Apr 25 16:21:07 2014 +0200 +++ b/src/cpu/x86/vm/sharedRuntime_x86_64.cpp Mon Apr 28 11:18:15 2014 +0200 @@ -3360,10 +3360,9 @@ #ifdef GRAAL int implicit_exception_uncommon_trap_offset = __ pc() - start; + __ pushptr(Address(r15_thread, in_bytes(JavaThread::graal_implicit_exception_pc_offset()))); - int uncommon_trap_offset = __ pc() - start; - // Save everything in sight. RegisterSaver::save_live_registers(masm, 0, &frame_size_in_words); // fetch_unroll_info needs to call last_java_frame() @@ -3643,7 +3642,6 @@ _deopt_blob = DeoptimizationBlob::create(&buffer, oop_maps, 0, exception_offset, reexecute_offset, frame_size_in_words); _deopt_blob->set_unpack_with_exception_in_tls_offset(exception_in_tls_offset); #ifdef GRAAL - _deopt_blob->set_uncommon_trap_offset(uncommon_trap_offset); _deopt_blob->set_implicit_exception_uncommon_trap_offset(implicit_exception_uncommon_trap_offset); #endif } diff -r 3dde8d8c95b8 -r 40d0022115ee src/cpu/x86/vm/vmStructs_x86.hpp --- a/src/cpu/x86/vm/vmStructs_x86.hpp Fri Apr 25 16:21:07 2014 +0200 +++ b/src/cpu/x86/vm/vmStructs_x86.hpp Mon Apr 28 11:18:15 2014 +0200 @@ -47,6 +47,8 @@ #define VM_INT_CONSTANTS_CPU(declare_constant, declare_preprocessor_constant, declare_c1_constant, declare_c2_constant, declare_c2_preprocessor_constant) \ declare_constant(frame::arg_reg_save_area_bytes) \ + declare_constant(frame::interpreter_frame_sender_sp_offset) \ + declare_constant(frame::interpreter_frame_last_sp_offset) \ declare_constant(VM_Version::CPU_CX8) \ declare_constant(VM_Version::CPU_CMOV) \ declare_constant(VM_Version::CPU_FXSR) \ diff -r 3dde8d8c95b8 -r 40d0022115ee src/gpu/hsail/vm/gpu_hsail.cpp --- a/src/gpu/hsail/vm/gpu_hsail.cpp Fri Apr 25 16:21:07 2014 +0200 +++ b/src/gpu/hsail/vm/gpu_hsail.cpp Mon Apr 28 11:18:15 2014 +0200 @@ -59,19 +59,19 @@ #define OBJECT "Ljava/lang/Object;" #define STRING "Ljava/lang/String;" +#define JLTHREAD "Ljava/lang/Thread;" #define HS_INSTALLED_CODE "Lcom/oracle/graal/hotspot/meta/HotSpotInstalledCode;" #define HS_COMPILED_NMETHOD "Lcom/oracle/graal/hotspot/HotSpotCompiledNmethod;" #define HS_NMETHOD "Lcom/oracle/graal/hotspot/meta/HotSpotNmethod;" -// public native void executeKernel(HotSpotNmethod kernel, int jobSize, int i, int j, Object[] args) throws InvalidInstalledCodeException; - JNINativeMethod Hsail::HSAIL_methods[] = { {CC"initialize", CC"()Z", FN_PTR(Hsail::initialize)}, {CC"generateKernel", CC"([B" STRING ")J", FN_PTR(Hsail::generate_kernel)}, - {CC"executeKernel0", CC"("HS_INSTALLED_CODE"I["OBJECT"["OBJECT")Z", FN_PTR(Hsail::execute_kernel_void_1d)}, + {CC"executeKernel0", CC"("HS_INSTALLED_CODE"I["OBJECT"["OBJECT"["JLTHREAD"I)Z", FN_PTR(Hsail::execute_kernel_void_1d)}, }; void * Hsail::_device_context = NULL; +jint Hsail::_notice_safepoints = false; Hsail::okra_create_context_func_t Hsail::_okra_create_context; Hsail::okra_create_kernel_func_t Hsail::_okra_create_kernel; @@ -86,6 +86,55 @@ Hsail::okra_clearargs_func_t Hsail::_okra_clearargs; Hsail::okra_register_heap_func_t Hsail::_okra_register_heap; +struct Stats { + int _dispatches; + int _deopts; + int _overflows; + bool _changeSeen; + +public: + Stats() { + _dispatches = _deopts = _overflows = 0; + _changeSeen = false; + } + + void incDeopts() { + _deopts++; + _changeSeen = true; + } + void incOverflows() { + _overflows++; + _changeSeen = true; + } + + void finishDispatch() { + _dispatches++; + if (_changeSeen) { + // print(); + _changeSeen = false; + } + } + + void print() { + tty->print_cr("Disp=%d, Deopts=%d, Ovflows=%d", _dispatches, _deopts, _overflows); + } + +}; + +static Stats kernelStats; + +//static jint in_kernel = 0; + +void Hsail::notice_safepoints() { + _notice_safepoints = true; +// if (TraceGPUInteraction) { +// tty->print_cr("[HSAIL] Notice safepoint in_kernel=%d", in_kernel); +// } +} + +void Hsail::ignore_safepoints() { + _notice_safepoints = false; +} void Hsail::register_heap() { // After the okra functions are set up and the heap is initialized, register the java heap with HSA @@ -97,10 +146,11 @@ _okra_register_heap(Universe::heap()->base(), Universe::heap()->capacity()); } -GPU_VMENTRY(jboolean, Hsail::execute_kernel_void_1d, (JNIEnv* env, jclass, jobject kernel_handle, jint dimX, jobject args_handle, jobject oops_save_handle)) +GPU_VMENTRY(jboolean, Hsail::execute_kernel_void_1d, (JNIEnv* env, jclass, jobject kernel_handle, jint dimX, jobject args, jobject oops_save, + jobject donor_threads, jint allocBytesPerWorkitem)) ResourceMark rm; - jlong nmethodValue = HotSpotInstalledCode::codeBlob(kernel_handle); + jlong nmethodValue = InstalledCode::address(kernel_handle); if (nmethodValue == 0) { SharedRuntime::throw_and_post_jvmti_exception(JavaThread::current(), vmSymbols::com_oracle_graal_api_code_InvalidInstalledCodeException(), NULL); } @@ -113,7 +163,7 @@ SharedRuntime::throw_and_post_jvmti_exception(JavaThread::current(), vmSymbols::com_oracle_graal_api_code_InvalidInstalledCodeException(), NULL); } - return execute_kernel_void_1d_internal((address) kernel, dimX, args_handle, mh, nm, oops_save_handle, CHECK_0); + return execute_kernel_void_1d_internal((address) kernel, dimX, args, mh, nm, oops_save, donor_threads, allocBytesPerWorkitem, CHECK_0); GPU_END static void showRanges(jboolean *a, int len) { @@ -133,10 +183,79 @@ } } -jboolean Hsail::execute_kernel_void_1d_internal(address kernel, int dimX, jobject args_handle, methodHandle& mh, nmethod *nm, jobject oops_save_handle, TRAPS) { +// fill and retire old tlab and get a new one +// if we can't get one, no problem someone will eventually do a gc +void Hsail::getNewTlabForDonorThread(ThreadLocalAllocBuffer* tlab, size_t tlabMinHsail) { + tlab->clear_before_allocation(); // fill and retire old tlab (will also check for null) + + // get a size for a new tlab that is at least tlabMinHsail. + size_t new_tlab_size = tlab->compute_size(tlabMinHsail); + if (new_tlab_size == 0) return; + + HeapWord* tlab_start = Universe::heap()->allocate_new_tlab(new_tlab_size); + if (tlab_start == NULL) return; + + // ..and clear it if required + if (ZeroTLAB) { + Copy::zero_to_words(tlab_start, new_tlab_size); + } + // and init the tlab pointers + tlab->fill(tlab_start, tlab_start, new_tlab_size); +} + +static void printTlabInfo (ThreadLocalAllocBuffer* tlab) { + HeapWord *start = tlab->start(); + HeapWord *top = tlab->top(); + HeapWord *end = tlab->end(); + // sizes are in bytes + size_t tlabFree = tlab->free() * HeapWordSize; + size_t tlabUsed = tlab->used() * HeapWordSize; + size_t tlabSize = tlabFree + tlabUsed; + double freePct = 100.0 * (double) tlabFree/(double) tlabSize; + tty->print_cr("(%p, %p, %p), siz=%ld, free=%ld (%f%%)", start, top, end, tlabSize, tlabFree, freePct); +} + +jboolean Hsail::execute_kernel_void_1d_internal(address kernel, int dimX, jobject args, methodHandle& mh, nmethod *nm, jobject oops_save, + jobject donor_threads, int allocBytesPerWorkitem, TRAPS) { ResourceMark rm(THREAD); - objArrayOop argsArray = (objArrayOop) JNIHandles::resolve(args_handle); + objArrayOop argsArray = (objArrayOop) JNIHandles::resolve(args); + + // TODO: avoid donor thread logic if kernel does not allocate + objArrayOop donorThreadObjects = (objArrayOop) JNIHandles::resolve(donor_threads); + int numDonorThreads = donorThreadObjects->length(); + guarantee(numDonorThreads > 0, "need at least one donor thread"); + JavaThread** donorThreads = NEW_RESOURCE_ARRAY(JavaThread*, numDonorThreads); + for (int i = 0; i < numDonorThreads; i++) { + donorThreads[i] = java_lang_Thread::thread(donorThreadObjects->obj_at(i)); + } + + + // compute tlabMinHsail based on number of workitems, number of donor + // threads, allocBytesPerWorkitem rounded up + size_t tlabMinHsail = (allocBytesPerWorkitem * dimX + (numDonorThreads - 1)) / numDonorThreads; + if (TraceGPUInteraction) { + tty->print_cr("computed tlabMinHsail = %d", tlabMinHsail); + } + + for (int i = 0; i < numDonorThreads; i++) { + JavaThread* donorThread = donorThreads[i]; + ThreadLocalAllocBuffer* tlab = &donorThread->tlab(); + if (TraceGPUInteraction) { + tty->print("donorThread %d, is %p, tlab at %p -> ", i, donorThread, tlab); + printTlabInfo(tlab); + } + + // note: this used vs. free limit checking should be based on some + // heuristic where we see how much this kernel tends to allocate + if ((tlab->end() == NULL) || (tlab->free() * HeapWordSize < tlabMinHsail)) { + getNewTlabForDonorThread(tlab, tlabMinHsail); + if (TraceGPUInteraction) { + tty->print("donorThread %d, refilled tlab, -> ", i); + printTlabInfo(tlab); + } + } + } // Reset the kernel arguments _okra_clearargs(kernel); @@ -146,10 +265,14 @@ e = new (ResourceObj::C_HEAP, mtInternal) HSAILDeoptimizationInfo(); e->set_never_ran_array(NEW_C_HEAP_ARRAY(jboolean, dimX, mtInternal)); memset(e->never_ran_array(), 0, dimX * sizeof(jboolean)); + e->set_donor_threads(donorThreads); } // This object sets up the kernel arguments HSAILKernelArguments hka((address) kernel, mh->signature(), argsArray, mh->is_static(), e); + if (TraceGPUInteraction) { + tty->print_cr("[HSAIL] range=%d", dimX); + } // if any object passed was null, throw an exception here // doing this means the kernel code can avoid null checks on the object parameters. @@ -165,25 +288,53 @@ // Run the kernel bool success = false; { - TraceTime t1("execute kernel", TraceGPUInteraction); + TraceTime t("execute kernel", TraceGPUInteraction); + + //in_kernel = 1; + // Run the kernel success = _okra_execute_with_range(kernel, dimX); + //in_kernel = 0; + } + + // fix up any tlab tops that overflowed + bool anyOverflows = false; + for (int i = 0; i < numDonorThreads; i++) { + JavaThread * donorThread = donorThreads[i]; + ThreadLocalAllocBuffer* tlab = &donorThread->tlab(); + if (tlab->top() > tlab->end()) { + anyOverflows = true; + long overflowAmount = (long) tlab->top() - (long) tlab->pf_top(); + // tlab->set_top is private this ugly hack gets around that + *(long *)((char *)tlab + in_bytes(tlab->top_offset())) = (long) tlab->pf_top(); + if (TraceGPUInteraction) { + tty->print_cr("donorThread %d at %p overflowed by %ld bytes, setting last good top to %p", i, donorThread, overflowAmount, tlab->top()); + } + } + } + if (anyOverflows) { + kernelStats.incOverflows(); } if (UseHSAILDeoptimization) { + kernelStats.incDeopts(); // check if any workitem requested a deopt // currently we only support at most one such workitem int deoptcode = e->deopt_occurred(); - if (deoptcode != 0) { - if (deoptcode != 1) { + if (deoptcode != 1) { + if (deoptcode == 0) { + if (TraceGPUInteraction && _notice_safepoints != 0) { + tty->print_cr("[HSAIL] observed safepoint during kernel"); + } + } else { // error condition detected in deopt code char msg[200]; sprintf(msg, "deopt error detected, slot for workitem %d was not empty", -1 * (deoptcode + 1)); guarantee(deoptcode == 1, msg); } + } else { { TraceTime t3("handle deoptimizing workitems", TraceGPUInteraction); - if (TraceGPUInteraction) { tty->print_cr("deopt happened."); HSAILKernelDeoptimization * pdeopt = &e->_deopt_save_states[0]; @@ -194,7 +345,7 @@ // the hsail frames in oops_save so they get adjusted by any // GC. Need to do this before leaving thread_in_vm mode. // resolve handle only needed once here (not exiting vm mode) - objArrayOop oopsSaveArray = (objArrayOop) JNIHandles::resolve(oops_save_handle); + objArrayOop oopsSaveArray = (objArrayOop) JNIHandles::resolve(oops_save); // since slots are allocated from the beginning, we know how far to look assert(e->num_deopts() < MAX_DEOPT_SAVE_STATES_SIZE, "deopt save state overflow"); @@ -228,7 +379,7 @@ // update the hsailFrame from the oopsSaveArray // re-resolve the handle - oopsSaveArray = (objArrayOop) JNIHandles::resolve(oops_save_handle); + oopsSaveArray = (objArrayOop) JNIHandles::resolve(oops_save); int dregOopMap = hsailFrame->dreg_oops_map(); for (int bit = 0; bit < 16; bit++) { @@ -276,51 +427,51 @@ tty->print_cr("[HSAIL] Deoptimizing to host completed for %d workitems", count_deoptimized); } } - - { - TraceTime t3("handle never-rans", TraceGPUInteraction); + } - // Handle any never_ran workitems if there were any - int count_never_ran = 0; - bool handleNeverRansHere = true; - // turn off verbose trace stuff for javacall arg setup - bool savedTraceGPUInteraction = TraceGPUInteraction; - TraceGPUInteraction = false; - jboolean *never_ran_array = e->never_ran_array(); - if (handleNeverRansHere) { - for (int k = 0; k < dimX; k++) { - if (never_ran_array[k]) { - // run it as a javaCall - KlassHandle methKlass = mh->method_holder(); - Thread* THREAD = Thread::current(); - JavaValue result(T_VOID); - JavaCallArguments javaArgs; - // re-resolve the args_handle here - objArrayOop resolvedArgsArray = (objArrayOop) JNIHandles::resolve(args_handle); - // This object sets up the javaCall arguments - // the way argsArray is set up, this should work for instance methods as well - // (the receiver will be the first oop pushed) - HSAILJavaCallArguments hjca(&javaArgs, k, mh->signature(), resolvedArgsArray, mh->is_static()); - if (mh->is_static()) { - JavaCalls::call_static(&result, methKlass, mh->name(), mh->signature(), &javaArgs, THREAD); - } else { - JavaCalls::call_virtual(&result, methKlass, mh->name(), mh->signature(), &javaArgs, THREAD); - } - count_never_ran++; + // Handle any never_ran workitems if there were any + { + TraceTime t("handle never-rans ", TraceGPUInteraction); + int count_never_ran = 0; + bool handleNeverRansHere = true; + // turn off verbose trace stuff for javacall arg setup + bool savedTraceGPUInteraction = TraceGPUInteraction; + TraceGPUInteraction = false; + jboolean *never_ran_array = e->never_ran_array(); + if (handleNeverRansHere) { + for (int k = 0; k < dimX; k++) { + if (never_ran_array[k]) { + // run it as a javaCall + KlassHandle methKlass = mh->method_holder(); + Thread* THREAD = Thread::current(); + JavaValue result(T_VOID); + JavaCallArguments javaArgs; + // re-resolve the args_handle here + objArrayOop resolvedArgsArray = (objArrayOop) JNIHandles::resolve(args); + // This object sets up the javaCall arguments + // the way argsArray is set up, this should work for instance methods as well + // (the receiver will be the first oop pushed) + HSAILJavaCallArguments hjca(&javaArgs, k, mh->signature(), resolvedArgsArray, mh->is_static()); + if (mh->is_static()) { + JavaCalls::call_static(&result, methKlass, mh->name(), mh->signature(), &javaArgs, THREAD); + } else { + JavaCalls::call_virtual(&result, methKlass, mh->name(), mh->signature(), &javaArgs, THREAD); } + count_never_ran++; } - TraceGPUInteraction = savedTraceGPUInteraction; - if (TraceGPUInteraction) { - tty->print_cr("%d workitems never ran, have been run via JavaCall", count_never_ran); - showRanges(never_ran_array, dimX); - } - } // end of never-ran handling - } + } + TraceGPUInteraction = savedTraceGPUInteraction; + if (TraceGPUInteraction) { + tty->print_cr("%d workitems never ran, have been run via JavaCall", count_never_ran); + showRanges(never_ran_array, dimX); + } + } // end of never-ran handling } FREE_C_HEAP_ARRAY(jboolean, e->never_ran_array(), mtInternal); delete e; } + kernelStats.finishDispatch(); return success; } @@ -361,7 +512,7 @@ #define LOOKUP_OKRA_FUNCTION(name, alias) \ _##alias = \ - CAST_TO_FN_PTR(alias##_func_t, os::dll_lookup(handle, STRINGIFY(name))); \ + CAST_TO_FN_PTR(alias##_func_t, os::dll_lookup(okra_lib_handle, STRINGIFY(name))); \ if (_##alias == NULL) { \ tty->print_cr("[HSAIL] ***** Error: Failed to lookup %s in %s, wrong version of OKRA?", STRINGIFY(name), okra_library_name); \ return false; \ @@ -377,22 +528,25 @@ // here we know we have a valid okra_library_name to try to load char ebuf[O_BUFLEN]; + char *okra_lib_name_from_env_var = getenv("_OKRA_SIM_LIB_PATH_"); + if (okra_lib_name_from_env_var != NULL) { + okra_library_name = okra_lib_name_from_env_var; + } if (TraceGPUInteraction) { - tty->print_cr("[HSAIL] library is %s", okra_library_name); + tty->print_cr("[HSAIL] library is %s", okra_library_name); } - - void *handle = os::dll_load(okra_library_name, ebuf, O_BUFLEN); - // try alternate location if env variable set - char *okra_lib_name_from_env_var = getenv("_OKRA_SIM_LIB_PATH_"); - if ((handle == NULL) && (okra_lib_name_from_env_var != NULL)) { - handle = os::dll_load(okra_lib_name_from_env_var, ebuf, O_BUFLEN); - if ((handle != NULL) && TraceGPUInteraction) { - tty->print_cr("[HSAIL] using _OKRA_SIM_LIB_PATH_=%s", getenv("_OKRA_SIM_LIB_PATH_")); - } - } - - if (handle == NULL) { - // Unable to dlopen okra + void *okra_lib_handle = NULL; +#if defined(LINUX) + // Check first if the Okra library is already loaded. + // TODO: Figure out how to do this on other OSes. + okra_lib_handle = ::dlopen(okra_library_name, RTLD_LAZY | RTLD_NOLOAD); +#endif + // If Okra library is not already loaded, load it here + if (okra_lib_handle == NULL) { + okra_lib_handle = os::dll_load(okra_library_name, ebuf, O_BUFLEN); + } + if (okra_lib_handle == NULL) { + // Unable to open Okra library if (TraceGPUInteraction) { tty->print_cr("[HSAIL] library load failed."); } @@ -401,7 +555,8 @@ guarantee(_okra_create_context == NULL, "cannot repeat GPU initialization"); - // at this point we know handle is valid and we can lookup the functions + // at this point we know okra_lib_handle is valid whether we loaded + // here or earlier. In either case, we can lookup the functions LOOKUP_OKRA_FUNCTION(okra_create_context, okra_create_context); LOOKUP_OKRA_FUNCTION(okra_create_kernel, okra_create_kernel); LOOKUP_OKRA_FUNCTION(okra_push_object, okra_push_object); @@ -416,7 +571,7 @@ LOOKUP_OKRA_FUNCTION(okra_register_heap, okra_register_heap); // if we made it this far, real success - gpu::initialized_gpu("Okra"); + Gpu::initialized_gpu(new Hsail()); return true; GPU_END diff -r 3dde8d8c95b8 -r 40d0022115ee src/gpu/hsail/vm/gpu_hsail.hpp --- a/src/gpu/hsail/vm/gpu_hsail.hpp Fri Apr 25 16:21:07 2014 +0200 +++ b/src/gpu/hsail/vm/gpu_hsail.hpp Mon Apr 28 11:18:15 2014 +0200 @@ -27,11 +27,9 @@ #include "utilities/exceptions.hpp" #include "graal/graalEnv.hpp" -// #include "graal/graalCodeInstaller.hpp" #include "gpu_hsail_Frame.hpp" -class Hsail { - friend class gpu; +class Hsail : public Gpu { public: class HSAILKernelDeoptimization { @@ -58,25 +56,28 @@ class HSAILDeoptimizationInfo : public ResourceObj { friend class VMStructs; private: + jint* _notice_safepoints; jint _deopt_occurred; jint _deopt_next_index; + JavaThread** _donor_threads; jboolean * _never_ran_array; public: HSAILKernelDeoptimization _deopt_save_states[MAX_DEOPT_SAVE_STATES_SIZE]; inline HSAILDeoptimizationInfo() { + _notice_safepoints = &Hsail::_notice_safepoints; _deopt_occurred = 0; _deopt_next_index = 0; } inline jint deopt_occurred() { - // Check that hsail did not write in the wrong place return _deopt_occurred; } inline jint num_deopts() { return _deopt_next_index; } inline jboolean *never_ran_array() { return _never_ran_array; } inline void set_never_ran_array(jboolean *p) { _never_ran_array = p; } + inline void set_donor_threads(JavaThread **threads) { _donor_threads = threads; } }; @@ -91,14 +92,17 @@ JNIEXPORT static jlong generate_kernel(JNIEnv *env, jclass, jbyteArray code_handle, jstring name_handle); // static native boolean executeKernel0(HotSpotInstalledCode kernel, int jobSize, Object[] args); - JNIEXPORT static jboolean execute_kernel_void_1d(JNIEnv *env, jclass, jobject hotspotInstalledCode, jint dimX, jobject args, jobject oopsSave); + JNIEXPORT static jboolean execute_kernel_void_1d(JNIEnv *env, jclass, jobject hotspotInstalledCode, jint dimX, jobject args, jobject oopsSave, + jobject donorThreads, int allocBytesPerWorkitem); + + // static native void getThreadPointers(Object[] donorThreads, long[] threadPointersOut); + JNIEXPORT static void get_thread_pointers(JNIEnv *env, jclass, jobject donor_threads_handle, jobject thread_ptrs_handle); - // static native void setSimulatorSingleThreaded0(); - JNIEXPORT static void setSimulatorSingleThreaded0(JNIEnv *env, jclass); + static void getNewTlabForDonorThread(ThreadLocalAllocBuffer* tlab, size_t tlabMinHsail); - - static jboolean execute_kernel_void_1d_internal(address kernel, int dimX, jobject args, methodHandle& mh, nmethod *nm, jobject oopsSave, TRAPS); - + static jboolean execute_kernel_void_1d_internal(address kernel, int dimX, jobject args, methodHandle& mh, nmethod *nm, jobject oopsSave, + jobject donor_threads, int allocBytesPerWorkitem, TRAPS); + static void register_heap(); static GraalEnv::CodeInstallResult install_code(Handle& compiled_code, CodeBlob*& cb, Handle installed_code, Handle triggered_deoptimizations); @@ -108,6 +112,11 @@ // Registers the implementations for the native methods in HSAILHotSpotBackend static bool register_natives(JNIEnv* env); + virtual const char* name() { return "HSAIL"; } + + virtual void notice_safepoints(); + virtual void ignore_safepoints(); + #if defined(__x86_64) || defined(AMD64) || defined(_M_AMD64) typedef unsigned long long CUdeviceptr; #else @@ -144,5 +153,8 @@ protected: static void* _device_context; + + // true if safepoints are activated + static jint _notice_safepoints; }; #endif // GPU_HSAIL_HPP diff -r 3dde8d8c95b8 -r 40d0022115ee src/gpu/hsail/vm/vmStructs_hsail.hpp --- a/src/gpu/hsail/vm/vmStructs_hsail.hpp Fri Apr 25 16:21:07 2014 +0200 +++ b/src/gpu/hsail/vm/vmStructs_hsail.hpp Mon Apr 28 11:18:15 2014 +0200 @@ -32,17 +32,19 @@ // constants required by the Serviceability Agent. This file is // referenced by vmStructs.cpp. -#define VM_STRUCTS_GPU_HSAIL(nonstatic_field) \ +#define VM_STRUCTS_GPU_HSAIL(nonstatic_field) \ nonstatic_field(HSAILFrame, _pc_offset, jint) \ nonstatic_field(HSAILFrame, _num_s_regs, jbyte) \ nonstatic_field(HSAILFrame, _save_area[0], jlong) \ - \ + \ nonstatic_field(Hsail::HSAILKernelDeoptimization, _workitemid, jint) \ nonstatic_field(Hsail::HSAILKernelDeoptimization, _actionAndReason, jint) \ - nonstatic_field(Hsail::HSAILKernelDeoptimization, _first_frame, HSAILFrame) \ - \ + nonstatic_field(Hsail::HSAILKernelDeoptimization, _first_frame, HSAILFrame) \ + \ + nonstatic_field(Hsail::HSAILDeoptimizationInfo, _notice_safepoints, jint*) \ nonstatic_field(Hsail::HSAILDeoptimizationInfo, _deopt_occurred, jint) \ nonstatic_field(Hsail::HSAILDeoptimizationInfo, _deopt_next_index, jint) \ + nonstatic_field(Hsail::HSAILDeoptimizationInfo, _donor_threads, JavaThread**) \ nonstatic_field(Hsail::HSAILDeoptimizationInfo, _never_ran_array, jboolean *) \ nonstatic_field(Hsail::HSAILDeoptimizationInfo, _deopt_save_states[0], Hsail::HSAILKernelDeoptimization) \ nonstatic_field(Hsail::HSAILDeoptimizationInfo, _deopt_save_states[1], Hsail::HSAILKernelDeoptimization) diff -r 3dde8d8c95b8 -r 40d0022115ee src/gpu/ptx/vm/gpu_ptx.cpp --- a/src/gpu/ptx/vm/gpu_ptx.cpp Fri Apr 25 16:21:07 2014 +0200 +++ b/src/gpu/ptx/vm/gpu_ptx.cpp Mon Apr 28 11:18:15 2014 +0200 @@ -271,7 +271,7 @@ tty->print_cr("[CUDA] Success: Created context for device: %d", _cu_device); } - gpu::initialized_gpu(device_name); + Gpu::initialized_gpu(new Ptx()); return true; GPU_END diff -r 3dde8d8c95b8 -r 40d0022115ee src/gpu/ptx/vm/gpu_ptx.hpp --- a/src/gpu/ptx/vm/gpu_ptx.hpp Fri Apr 25 16:21:07 2014 +0200 +++ b/src/gpu/ptx/vm/gpu_ptx.hpp Mon Apr 28 11:18:15 2014 +0200 @@ -93,7 +93,7 @@ #define GRAAL_SUPPORTED_COMPUTE_CAPABILITY_VERSION 3.0 -class Ptx { +class Ptx : public Gpu { friend class PtxCall; private: @@ -120,6 +120,9 @@ static int ncores(int major, int minor); public: + + virtual const char* name() { return "PTX"; } + // Registers the implementations for the native methods in PTXHotSpotBackend static bool register_natives(JNIEnv* env); diff -r 3dde8d8c95b8 -r 40d0022115ee src/os/bsd/vm/gpu_bsd.cpp --- a/src/os/bsd/vm/gpu_bsd.cpp Fri Apr 25 16:21:07 2014 +0200 +++ b/src/os/bsd/vm/gpu_bsd.cpp Mon Apr 28 11:18:15 2014 +0200 @@ -27,7 +27,7 @@ #include "hsail/vm/gpu_hsail.hpp" #include "utilities/ostream.hpp" -jobject gpu::probe_gpus(JNIEnv* env) { +jobject Gpu::probe_gpus(JNIEnv* env) { #ifdef __APPLE__ /* * Let the CUDA driver initialization be the gate to GPU for now, pending diff -r 3dde8d8c95b8 -r 40d0022115ee src/os/linux/vm/gpu_linux.cpp --- a/src/os/linux/vm/gpu_linux.cpp Fri Apr 25 16:21:07 2014 +0200 +++ b/src/os/linux/vm/gpu_linux.cpp Mon Apr 28 11:18:15 2014 +0200 @@ -38,7 +38,7 @@ #define PCI_DRIVER_NAME_START_POS 255 -jobject gpu::probe_gpus(JNIEnv* env) { +jobject Gpu::probe_gpus(JNIEnv* env) { bool hsail = false; bool ptx = false; diff -r 3dde8d8c95b8 -r 40d0022115ee src/os/windows/vm/gpu_windows.cpp --- a/src/os/windows/vm/gpu_windows.cpp Fri Apr 25 16:21:07 2014 +0200 +++ b/src/os/windows/vm/gpu_windows.cpp Mon Apr 28 11:18:15 2014 +0200 @@ -27,7 +27,7 @@ #include "hsail/vm/gpu_hsail.hpp" #include "utilities/ostream.hpp" -jobject gpu::probe_gpus(JNIEnv* env) { +jobject Gpu::probe_gpus(JNIEnv* env) { // TODO: add detection of PTX/NVidia if (Hsail::register_natives(env)) { return env->NewStringUTF("HSAIL"); diff -r 3dde8d8c95b8 -r 40d0022115ee src/share/vm/classfile/systemDictionary.hpp --- a/src/share/vm/classfile/systemDictionary.hpp Fri Apr 25 16:21:07 2014 +0200 +++ b/src/share/vm/classfile/systemDictionary.hpp Mon Apr 28 11:18:15 2014 +0200 @@ -186,6 +186,9 @@ /* Support for Graal */ \ do_klass(CompilerThread_klass, com_oracle_graal_compiler_CompilerThread, Opt) \ do_klass(BitSet_klass, java_util_BitSet, Opt) \ + /* graal.graph */ \ + do_klass(Node_klass, com_oracle_graal_graph_Node, Opt) \ + do_klass(NodeClass_klass, com_oracle_graal_graph_NodeClass, Opt) \ /* graal.hotspot */ \ do_klass(HotSpotCompiledCode_klass, com_oracle_graal_hotspot_HotSpotCompiledCode, Opt) \ do_klass(HotSpotCompiledCode_Comment_klass, com_oracle_graal_hotspot_HotSpotCompiledCode_Comment, Opt) \ @@ -227,6 +230,7 @@ do_klass(CompilationResult_Site_klass, com_oracle_graal_api_code_CompilationResult_Site, Opt) \ do_klass(ExternalCompilationResult_klass, com_oracle_graal_gpu_ExternalCompilationResult, Opt) \ do_klass(InfopointReason_klass, com_oracle_graal_api_code_InfopointReason, Opt) \ + do_klass(InstalledCode_klass, com_oracle_graal_api_code_InstalledCode, Opt) \ do_klass(code_Register_klass, com_oracle_graal_api_code_Register, Opt) \ do_klass(RegisterValue_klass, com_oracle_graal_api_code_RegisterValue, Opt) \ do_klass(StackSlot_klass, com_oracle_graal_api_code_StackSlot, Opt) \ diff -r 3dde8d8c95b8 -r 40d0022115ee src/share/vm/classfile/vmSymbols.hpp --- a/src/share/vm/classfile/vmSymbols.hpp Fri Apr 25 16:21:07 2014 +0200 +++ b/src/share/vm/classfile/vmSymbols.hpp Mon Apr 28 11:18:15 2014 +0200 @@ -292,6 +292,9 @@ /* Support for Graal */ \ template(com_oracle_graal_compiler_CompilerThread, "com/oracle/graal/compiler/CompilerThread") \ template(java_util_BitSet, "java/util/BitSet") \ + /* graal.graph */ \ + template(com_oracle_graal_graph_Node, "com/oracle/graal/graph/Node") \ + template(com_oracle_graal_graph_NodeClass, "com/oracle/graal/graph/NodeClass") \ /* graal.hotspot */ \ template(com_oracle_graal_hotspot_HotSpotGraalRuntime, "com/oracle/graal/hotspot/HotSpotGraalRuntime") \ template(com_oracle_graal_hotspot_HotSpotKlassOop, "com/oracle/graal/hotspot/HotSpotKlassOop") \ @@ -344,6 +347,7 @@ template(com_oracle_graal_api_code_CompilationResult_Infopoint, "com/oracle/graal/api/code/CompilationResult$Infopoint") \ template(com_oracle_graal_api_code_CompilationResult_Site, "com/oracle/graal/api/code/CompilationResult$Site") \ template(com_oracle_graal_api_code_InfopointReason, "com/oracle/graal/api/code/InfopointReason") \ + template(com_oracle_graal_api_code_InstalledCode, "com/oracle/graal/api/code/InstalledCode") \ template(com_oracle_graal_api_code_BytecodeFrame, "com/oracle/graal/api/code/BytecodeFrame") \ template(com_oracle_graal_api_code_BytecodePosition, "com/oracle/graal/api/code/BytecodePosition") \ template(com_oracle_graal_api_code_DebugInfo, "com/oracle/graal/api/code/DebugInfo") \ diff -r 3dde8d8c95b8 -r 40d0022115ee src/share/vm/code/codeBlob.hpp --- a/src/share/vm/code/codeBlob.hpp Fri Apr 25 16:21:07 2014 +0200 +++ b/src/share/vm/code/codeBlob.hpp Mon Apr 28 11:18:15 2014 +0200 @@ -358,8 +358,6 @@ int _unpack_with_exception_in_tls; #ifdef GRAAL - // (thomaswue) Offset when Graal calls uncommon_trap. - int _uncommon_trap_offset; int _implicit_exception_uncommon_trap_offset; #endif @@ -417,12 +415,6 @@ address unpack_with_exception_in_tls() const { return code_begin() + _unpack_with_exception_in_tls; } #ifdef GRAAL - // (thomaswue) Offset when Graal calls uncommon_trap. - void set_uncommon_trap_offset(int offset) { - _uncommon_trap_offset = offset; - assert(contains(code_begin() + _uncommon_trap_offset), "must be PC inside codeblob"); - } - address uncommon_trap() const { return code_begin() + _uncommon_trap_offset; } void set_implicit_exception_uncommon_trap_offset(int offset) { _implicit_exception_uncommon_trap_offset = offset; assert(contains(code_begin() + _implicit_exception_uncommon_trap_offset), "must be PC inside codeblob"); diff -r 3dde8d8c95b8 -r 40d0022115ee src/share/vm/code/compiledIC.cpp --- a/src/share/vm/code/compiledIC.cpp Fri Apr 25 16:21:07 2014 +0200 +++ b/src/share/vm/code/compiledIC.cpp Mon Apr 28 11:18:15 2014 +0200 @@ -228,11 +228,13 @@ bool is_monomorphic = (cb != NULL && cb->is_nmethod()); // Check that the cached_value is a klass for non-optimized monomorphic calls // This assertion is invalid for compiler1: a call that does not look optimized (no static stub) can be used - // for calling directly to vep without using the inline cache (i.e., cached_value == NULL) + // for calling directly to vep without using the inline cache (i.e., cached_value == NULL). + // For Graal this occurs because CHA is only used to improve inlining so call sites which could be optimized + // virtuals because there are no currently loaded subclasses of a type are left as virtual call sites. #ifdef ASSERT CodeBlob* caller = CodeCache::find_blob_unsafe(instruction_address()); - bool is_c1_method = caller->is_compiled_by_c1(); - assert( is_c1_method || + bool is_c1_or_graal_method = caller->is_compiled_by_c1() || caller->is_compiled_by_graal(); + assert( is_c1_or_graal_method || !is_monomorphic || is_optimized() || (cached_metadata() != NULL && cached_metadata()->is_klass()), "sanity check"); diff -r 3dde8d8c95b8 -r 40d0022115ee src/share/vm/code/debugInfoRec.cpp --- a/src/share/vm/code/debugInfoRec.cpp Fri Apr 25 16:21:07 2014 +0200 +++ b/src/share/vm/code/debugInfoRec.cpp Mon Apr 28 11:18:15 2014 +0200 @@ -235,10 +235,16 @@ int DebugInformationRecorder::find_sharable_decode_offset(int stream_offset) { + // It's always a space win to share and Graal generates quite a bit + // of scopes data so always enable the sharing logic with Graal. + // Presumably this is disabled in regular HotSpot because it makes + // recording more expensive? +#ifndef GRAAL // Only pull this trick if non-safepoint recording // is enabled, for now. if (!recording_non_safepoints()) return serialized_null; +#endif NOT_PRODUCT(++dir_stats.chunks_queried); int stream_length = stream()->position() - stream_offset; diff -r 3dde8d8c95b8 -r 40d0022115ee src/share/vm/code/nmethod.cpp --- a/src/share/vm/code/nmethod.cpp Fri Apr 25 16:21:07 2014 +0200 +++ b/src/share/vm/code/nmethod.cpp Mon Apr 28 11:18:15 2014 +0200 @@ -1330,7 +1330,7 @@ // Java wrapper is no longer alive. Here we need to clear out this weak // reference to the dead object. if (_graal_installed_code != NULL) { - HotSpotInstalledCode::set_codeBlob(_graal_installed_code, 0); + InstalledCode::set_address(_graal_installed_code, 0); _graal_installed_code = NULL; } #endif @@ -1510,8 +1510,8 @@ } #ifdef GRAAL if (_graal_installed_code != NULL) { - // Break the link between nmethod and HotSpotInstalledCode such that the nmethod can subsequently be flushed safely. - HotSpotInstalledCode::set_codeBlob(_graal_installed_code, 0); + // Break the link between nmethod and InstalledCode such that the nmethod can subsequently be flushed safely. + InstalledCode::set_address(_graal_installed_code, 0); } #endif @@ -1738,7 +1738,7 @@ #ifdef GRAAL // Follow Graal method if (_graal_installed_code != NULL) { - if (HotSpotNmethod::isDefault(_graal_installed_code)) { + if (_graal_installed_code->is_a(HotSpotNmethod::klass()) && HotSpotNmethod::isDefault(_graal_installed_code)) { if (!is_alive->do_object_b(_graal_installed_code)) { _graal_installed_code = NULL; } diff -r 3dde8d8c95b8 -r 40d0022115ee src/share/vm/compiler/disassembler.cpp --- a/src/share/vm/compiler/disassembler.cpp Fri Apr 25 16:21:07 2014 +0200 +++ b/src/share/vm/compiler/disassembler.cpp Mon Apr 28 11:18:15 2014 +0200 @@ -522,7 +522,7 @@ nm->method()->method_holder()->name()->print_symbol_on(env.output()); env.output()->print("."); nm->method()->name()->print_symbol_on(env.output()); - env.output()->print_cr(" [" PTR_FORMAT ", " PTR_FORMAT "] %d bytes", p, end, ((jlong)(end - p)) * sizeof(unsigned char*)); + env.output()->print_cr(" [" PTR_FORMAT ", " PTR_FORMAT "] %d bytes", p, end, ((jlong)(end - p))); // If there has been profiling, print the buckets. if (FlatProfiler::bucket_start_for(p) != NULL) { diff -r 3dde8d8c95b8 -r 40d0022115ee src/share/vm/gc_interface/collectedHeap.hpp --- a/src/share/vm/gc_interface/collectedHeap.hpp Fri Apr 25 16:21:07 2014 +0200 +++ b/src/share/vm/gc_interface/collectedHeap.hpp Mon Apr 28 11:18:15 2014 +0200 @@ -84,6 +84,7 @@ class CollectedHeap : public CHeapObj { friend class VMStructs; friend class IsGCActiveMark; // Block structured external access to _is_gc_active + friend class Hsail; // access to allocate_new_tlab #ifdef ASSERT static int _fire_out_of_memory_count; diff -r 3dde8d8c95b8 -r 40d0022115ee src/share/vm/graal/graalCodeInstaller.cpp --- a/src/share/vm/graal/graalCodeInstaller.cpp Fri Apr 25 16:21:07 2014 +0200 +++ b/src/share/vm/graal/graalCodeInstaller.cpp Mon Apr 28 11:18:15 2014 +0200 @@ -455,8 +455,7 @@ _code = (arrayOop) CompilationResult::targetCode(comp_result); _code_size = CompilationResult::targetCodeSize(comp_result); - // The frame size we get from the target method does not include the return address, so add one word for it here. - _total_frame_size = CompilationResult::frameSize(comp_result) + HeapWordSize; // FIXME this is an x86-ism + _total_frame_size = CompilationResult::totalFrameSize(comp_result); _custom_stack_area_offset = CompilationResult::customStackAreaOffset(comp_result); // Pre-calculate the constants section size. This is required for PC-relative addressing. @@ -677,8 +676,11 @@ oop hotspot_method = BytecodePosition::method(frame); Method* method = getMethodFromHotSpotMethod(hotspot_method); jint bci = BytecodePosition::bci(frame); + if (bci == BytecodeFrame::BEFORE_BCI()) { + bci = SynchronizationEntryBCI; + } bool reexecute; - if (bci == -1 || bci == -2){ + if (bci == SynchronizationEntryBCI){ reexecute = false; } else { Bytecodes::Code code = Bytecodes::java_code_at(method, method->bcp_from(bci)); diff -r 3dde8d8c95b8 -r 40d0022115ee src/share/vm/graal/graalCodeInstaller.hpp --- a/src/share/vm/graal/graalCodeInstaller.hpp Fri Apr 25 16:21:07 2014 +0200 +++ b/src/share/vm/graal/graalCodeInstaller.hpp Mon Apr 28 11:18:15 2014 +0200 @@ -130,20 +130,4 @@ */ Method* getMethodFromHotSpotMethod(oop hotspot_method); -#ifdef TARGET_ARCH_x86 -# include "graalCodeInstaller_x86.hpp" -#endif -#ifdef TARGET_ARCH_sparc -# include "graalCodeInstaller_sparc.hpp" -#endif -#ifdef TARGET_ARCH_zero -# error -#endif -#ifdef TARGET_ARCH_arm -# error -#endif -#ifdef TARGET_ARCH_ppc -# error -#endif - #endif // SHARE_VM_GRAAL_GRAAL_CODE_INSTALLER_HPP diff -r 3dde8d8c95b8 -r 40d0022115ee src/share/vm/graal/graalCompiler.cpp --- a/src/share/vm/graal/graalCompiler.cpp Fri Apr 25 16:21:07 2014 +0200 +++ b/src/share/vm/graal/graalCompiler.cpp Mon Apr 28 11:18:15 2014 +0200 @@ -101,12 +101,10 @@ _external_deopt_i2c_entry = create_external_deopt_i2c(); #ifdef COMPILERGRAAL bool bootstrap = FLAG_IS_DEFAULT(BootstrapGraal) ? !TieredCompilation : BootstrapGraal; - bool hostedOnly = false; #else bool bootstrap = false; - bool hostedOnly = true; #endif - VMToCompiler::startCompiler(bootstrap, hostedOnly); + VMToCompiler::startCompiler(bootstrap); _initialized = true; CompilationPolicy::completed_vm_startup(); if (bootstrap) { diff -r 3dde8d8c95b8 -r 40d0022115ee src/share/vm/graal/graalCompilerToVM.cpp --- a/src/share/vm/graal/graalCompilerToVM.cpp Fri Apr 25 16:21:07 2014 +0200 +++ b/src/share/vm/graal/graalCompilerToVM.cpp Mon Apr 28 11:18:15 2014 +0200 @@ -157,7 +157,6 @@ //------------------------------------------------------------------------------------------------ set_address("handleDeoptStub", SharedRuntime::deopt_blob()->unpack()); - set_address("uncommonTrapStub", SharedRuntime::deopt_blob()->uncommon_trap()); set_address("registerFinalizerAddress", SharedRuntime::register_finalizer); set_address("exceptionHandlerForReturnAddressAddress", SharedRuntime::exception_handler_for_return_address); @@ -191,6 +190,10 @@ set_address("writeBarrierPostAddress", GraalRuntime::write_barrier_post); set_address("validateObject", GraalRuntime::validate_object); + set_address("deoptimizationFetchUnrollInfo", Deoptimization::fetch_unroll_info); + set_address("deoptimizationUncommonTrap", Deoptimization::uncommon_trap); + set_address("deoptimizationUnpackFrames", Deoptimization::unpack_frames); + //------------------------------------------------------------------------------------------------ set_int("graalCountersThreadOffset", in_bytes(JavaThread::graal_counters_offset())); @@ -207,6 +210,7 @@ #undef set_boolean #undef set_int #undef set_long +#undef set_address C2V_END @@ -527,15 +531,16 @@ assert(cb == NULL, "should be"); } else { if (!installed_code_handle.is_null()) { - assert(installed_code_handle->is_a(HotSpotInstalledCode::klass()), "wrong type"); - HotSpotInstalledCode::set_codeBlob(installed_code_handle, (jlong) cb); + assert(installed_code_handle->is_a(InstalledCode::klass()), "wrong type"); + InstalledCode::set_address(installed_code_handle, (jlong) cb); + InstalledCode::set_version(installed_code_handle, InstalledCode::version(installed_code_handle) + 1); oop comp_result = HotSpotCompiledCode::comp(compiled_code_handle); if (comp_result->is_a(ExternalCompilationResult::klass())) { if (TraceGPUInteraction) { tty->print_cr("installCode0: ExternalCompilationResult"); } HotSpotInstalledCode::set_codeStart(installed_code_handle, ExternalCompilationResult::entryPoint(comp_result)); - } else { + } else if (installed_code_handle->is_a(HotSpotInstalledCode::klass())) { HotSpotInstalledCode::set_size(installed_code_handle, cb->size()); HotSpotInstalledCode::set_codeStart(installed_code_handle, (jlong) cb->code_begin()); HotSpotInstalledCode::set_codeSize(installed_code_handle, cb->code_size()); @@ -557,8 +562,10 @@ stats->_standard.update(timer, processedBytecodes); } Handle installed_code_handle = JNIHandles::resolve(installed_code); - stats->_nmethods_size += HotSpotInstalledCode::size(installed_code_handle); - stats->_nmethods_code_size += HotSpotInstalledCode::codeSize(installed_code_handle); + if (installed_code_handle->is_a(HotSpotInstalledCode::klass())) { + stats->_nmethods_size += HotSpotInstalledCode::size(installed_code_handle); + stats->_nmethods_code_size += HotSpotInstalledCode::codeSize(installed_code_handle); + } if (CITimeEach) { methodHandle method = asMethod(HotSpotResolvedJavaMethod::metaspaceMethod(hotspot_method)); @@ -630,7 +637,7 @@ ResourceMark rm; HandleMark hm; - jlong nmethodValue = HotSpotInstalledCode::codeBlob(hotspotInstalledCode); + jlong nmethodValue = InstalledCode::address(hotspotInstalledCode); if (nmethodValue == 0L) { THROW_(vmSymbols::com_oracle_graal_api_code_InvalidInstalledCodeException(), NULL); } @@ -721,14 +728,14 @@ C2V_VMENTRY(void, invalidateInstalledCode, (JNIEnv *env, jobject, jobject hotspotInstalledCode)) - jlong nativeMethod = HotSpotInstalledCode::codeBlob(hotspotInstalledCode); + jlong nativeMethod = InstalledCode::address(hotspotInstalledCode); nmethod* m = (nmethod*)nativeMethod; if (m != NULL && !m->is_not_entrant()) { m->mark_for_deoptimization(); VM_Deoptimize op; VMThread::execute(&op); } - HotSpotInstalledCode::set_codeBlob(hotspotInstalledCode, 0); + InstalledCode::set_address(hotspotInstalledCode, 0); C2V_END C2V_VMENTRY(jobject, getJavaMirror, (JNIEnv *env, jobject, jlong metaspace_klass)) @@ -736,12 +743,6 @@ return JNIHandles::make_local(klass->java_mirror()); C2V_END -C2V_VMENTRY(void, setNodeClass, (JNIEnv *env, jobject, jobject java_class_handle, jobject value)) - oop java_class = JNIHandles::resolve(java_class_handle); - InstanceKlass* iklass = (InstanceKlass*) java_lang_Class::as_Klass(java_class); - iklass->set_graal_node_class(JNIHandles::resolve(value)); -C2V_END - C2V_VMENTRY(jlong, readUnsafeKlassPointer, (JNIEnv *env, jobject, jobject o)) oop resolved_o = JNIHandles::resolve(o); jlong klass = (jlong)(address)resolved_o->klass(); @@ -756,7 +757,7 @@ C2V_ENTRY(jobject, getGPUs, (JNIEnv *env, jobject)) #if defined(TARGET_OS_FAMILY_bsd) || defined(TARGET_OS_FAMILY_linux) || defined(TARGET_OS_FAMILY_windows) - return gpu::probe_gpus(env); + return Gpu::probe_gpus(env); #else return env->NewStringUTF(""); #endif @@ -786,12 +787,21 @@ return tty->time_stamp().milliseconds(); C2V_END -// public native HotSpotStackFrameReference getNextStackFrame(HotSpotStackFrameReference frame, ResolvedJavaMethod method); -C2V_VMENTRY(jobject, getNextStackFrame, (JNIEnv *env, jobject compilerToVM, jobject hs_frame, jobject hs_method)) +bool matches(jlongArray methods, Method* method) { + typeArrayOop methods_oop = (typeArrayOop) JNIHandles::resolve(methods); + + for (int i = 0; i < methods_oop->length(); i++) { + if (methods_oop->long_at(i) == (jlong) method) { + return true; + } + } + return false; +} + +C2V_VMENTRY(jobject, getNextStackFrame, (JNIEnv *env, jobject compilerToVM, jobject hs_frame, jlongArray methods, jint initialSkip)) ResourceMark rm; if (!thread->has_last_Java_frame()) return NULL; - methodHandle method = hs_method == NULL ? NULL : asMethod(HotSpotResolvedJavaMethod::metaspaceMethod(hs_method)); Handle result = InstanceKlass::cast(HotSpotStackFrameReference::klass())->allocate_instance(thread); HotSpotStackFrameReference::klass()->initialize(thread); @@ -840,48 +850,48 @@ if (vf->is_compiled_frame()) { // compiled method frame compiledVFrame* cvf = compiledVFrame::cast(vf); - if (method == NULL || cvf->method() == method()) { - GrowableArray* objects = cvf->scope()->objects(); - bool reallocated = false; - if (objects != NULL) { - reallocated = Deoptimization::realloc_objects(thread, fst.current(), objects, THREAD); - if (reallocated) { - Deoptimization::reassign_fields(fst.current(), fst.register_map(), objects); + if (methods == NULL || matches(methods, cvf->method())) { + if (initialSkip > 0) { + initialSkip --; + } else { + GrowableArray* objects = cvf->scope()->objects(); + bool reallocated = false; + if (objects != NULL) { + reallocated = Deoptimization::realloc_objects(thread, fst.current(), objects, THREAD); + if (reallocated) { + Deoptimization::reassign_fields(fst.current(), fst.register_map(), objects); + } + + GrowableArray* local_values = cvf->scope()->locals(); + typeArrayHandle array = oopFactory::new_boolArray(local_values->length(), thread); + for (int i = 0; i < local_values->length(); i++) { + ScopeValue* value = local_values->at(i); + if (value->is_object()) { + array->bool_at_put(i, true); + } + } + HotSpotStackFrameReference::set_localIsVirtual(result, array()); + } else { + HotSpotStackFrameReference::set_localIsVirtual(result, NULL); } - GrowableArray* local_values = cvf->scope()->locals(); - typeArrayHandle array = oopFactory::new_boolArray(local_values->length(), thread); - for (int i = 0; i < local_values->length(); i++) { - ScopeValue* value = local_values->at(i); - if (value->is_object()) { - array->bool_at_put(i, true); - } - } - HotSpotStackFrameReference::set_localIsVirtual(result, array()); - } else { - HotSpotStackFrameReference::set_localIsVirtual(result, NULL); - } - - locals = cvf->locals(); - HotSpotStackFrameReference::set_bci(result, cvf->bci()); - if (hs_method == NULL) { + locals = cvf->locals(); + HotSpotStackFrameReference::set_bci(result, cvf->bci()); HotSpotStackFrameReference::set_metaspaceMethod(result, (jlong) cvf->method()); - } else { - HotSpotStackFrameReference::set_metaspaceMethod(result, (jlong) method()); } } } else if (vf->is_interpreted_frame()) { // interpreted method frame interpretedVFrame* ivf = interpretedVFrame::cast(vf); - if (method == NULL || ivf->method() == method()) { - locals = ivf->locals(); - HotSpotStackFrameReference::set_bci(result, ivf->bci()); - if (hs_method == NULL) { + if (methods == NULL || matches(methods, ivf->method())) { + if (initialSkip > 0) { + initialSkip --; + } else { + locals = ivf->locals(); + HotSpotStackFrameReference::set_bci(result, ivf->bci()); HotSpotStackFrameReference::set_metaspaceMethod(result, (jlong) ivf->method()); - } else { - HotSpotStackFrameReference::set_metaspaceMethod(result, (jlong) method()); + HotSpotStackFrameReference::set_localIsVirtual(result, NULL); } - HotSpotStackFrameReference::set_localIsVirtual(result, NULL); } } @@ -923,7 +933,13 @@ return NULL; C2V_END - +C2V_VMENTRY(void, resolveInvokeDynamic, (JNIEnv *env, jobject, jlong metaspace_constant_pool, jint index)) + ConstantPool* cp = (ConstantPool*)metaspace_constant_pool; + CallInfo callInfo; + LinkResolver::resolve_invokedynamic(callInfo, cp, index, CHECK); + ConstantPoolCacheEntry* cp_cache_entry = cp->invokedynamic_cp_cache_entry_at(index); + cp_cache_entry->set_dynamic_call(cp, callInfo); +C2V_END // public native void materializeVirtualObjects(HotSpotStackFrameReference stackFrame, boolean invalidate); C2V_VMENTRY(void, materializeVirtualObjects, (JNIEnv *env, jobject, jobject hs_frame, bool invalidate)) @@ -1031,9 +1047,10 @@ #define CLASS "Ljava/lang/Class;" #define STACK_TRACE_ELEMENT "Ljava/lang/StackTraceElement;" #define HS_RESOLVED_METHOD "Lcom/oracle/graal/hotspot/meta/HotSpotResolvedJavaMethod;" +#define RESOLVED_METHOD "Lcom/oracle/graal/api/meta/ResolvedJavaMethod;" #define HS_COMPILED_CODE "Lcom/oracle/graal/hotspot/HotSpotCompiledCode;" #define HS_CONFIG "Lcom/oracle/graal/hotspot/HotSpotVMConfig;" -#define HS_INSTALLED_CODE "Lcom/oracle/graal/hotspot/meta/HotSpotInstalledCode;" +#define INSTALLED_CODE "Lcom/oracle/graal/api/code/InstalledCode;" #define NODE_CLASS "Lcom/oracle/graal/graph/NodeClass;" #define HS_STACK_FRAME_REF "Lcom/oracle/graal/hotspot/HotSpotStackFrameReference;" #define METASPACE_KLASS "J" @@ -1067,25 +1084,25 @@ {CC"lookupMethodInPool", CC"("METASPACE_CONSTANT_POOL"IB)"METASPACE_METHOD, FN_PTR(lookupMethodInPool)}, {CC"constantPoolRemapInstructionOperandFromCache", CC"("METASPACE_CONSTANT_POOL"I)I", FN_PTR(constantPoolRemapInstructionOperandFromCache)}, {CC"resolveField", CC"("METASPACE_CONSTANT_POOL"IB[J)"METASPACE_KLASS, FN_PTR(resolveField)}, + {CC"resolveInvokeDynamic", CC"("METASPACE_CONSTANT_POOL"I)V", FN_PTR(resolveInvokeDynamic)}, {CC"resolveMethod", CC"("METASPACE_KLASS STRING STRING")"METASPACE_METHOD, FN_PTR(resolveMethod)}, {CC"getClassInitializer", CC"("METASPACE_KLASS")"METASPACE_METHOD, FN_PTR(getClassInitializer)}, {CC"hasFinalizableSubclass", CC"("METASPACE_KLASS")Z", FN_PTR(hasFinalizableSubclass)}, {CC"getMaxCallTargetOffset", CC"(J)J", FN_PTR(getMaxCallTargetOffset)}, {CC"getMetaspaceMethod", CC"("CLASS"I)"METASPACE_METHOD, FN_PTR(getMetaspaceMethod)}, {CC"initializeConfiguration", CC"("HS_CONFIG")V", FN_PTR(initializeConfiguration)}, - {CC"installCode0", CC"("HS_COMPILED_CODE HS_INSTALLED_CODE SPECULATION_LOG")I", FN_PTR(installCode0)}, - {CC"notifyCompilationStatistics", CC"(I"HS_RESOLVED_METHOD"ZIJJ"HS_INSTALLED_CODE")V", FN_PTR(notifyCompilationStatistics)}, + {CC"installCode0", CC"("HS_COMPILED_CODE INSTALLED_CODE SPECULATION_LOG")I", FN_PTR(installCode0)}, + {CC"notifyCompilationStatistics", CC"(I"HS_RESOLVED_METHOD"ZIJJ"INSTALLED_CODE")V", FN_PTR(notifyCompilationStatistics)}, {CC"printCompilationStatistics", CC"(ZZ)V", FN_PTR(printCompilationStatistics)}, {CC"resetCompilationStatistics", CC"()V", FN_PTR(resetCompilationStatistics)}, {CC"disassembleCodeBlob", CC"(J)"STRING, FN_PTR(disassembleCodeBlob)}, - {CC"executeCompiledMethodVarargs", CC"(["OBJECT HS_INSTALLED_CODE")"OBJECT, FN_PTR(executeCompiledMethodVarargs)}, + {CC"executeCompiledMethodVarargs", CC"(["OBJECT INSTALLED_CODE")"OBJECT, FN_PTR(executeCompiledMethodVarargs)}, {CC"getLineNumberTable", CC"("METASPACE_METHOD")[J", FN_PTR(getLineNumberTable)}, {CC"getLocalVariableTableStart", CC"("METASPACE_METHOD")J", FN_PTR(getLocalVariableTableStart)}, {CC"getLocalVariableTableLength", CC"("METASPACE_METHOD")I", FN_PTR(getLocalVariableTableLength)}, {CC"reprofile", CC"("METASPACE_METHOD")V", FN_PTR(reprofile)}, - {CC"invalidateInstalledCode", CC"("HS_INSTALLED_CODE")V", FN_PTR(invalidateInstalledCode)}, + {CC"invalidateInstalledCode", CC"("INSTALLED_CODE")V", FN_PTR(invalidateInstalledCode)}, {CC"getJavaMirror", CC"("METASPACE_KLASS")"CLASS, FN_PTR(getJavaMirror)}, - {CC"setNodeClass", CC"("CLASS NODE_CLASS")V", FN_PTR(setNodeClass)}, {CC"readUnsafeKlassPointer", CC"("OBJECT")J", FN_PTR(readUnsafeKlassPointer)}, {CC"collectCounters", CC"()[J", FN_PTR(collectCounters)}, {CC"getGPUs", CC"()"STRING, FN_PTR(getGPUs)}, @@ -1093,7 +1110,7 @@ {CC"isMature", CC"("METASPACE_METHOD_DATA")Z", FN_PTR(isMature)}, {CC"hasCompiledCodeForOSR", CC"("METASPACE_METHOD"II)Z", FN_PTR(hasCompiledCodeForOSR)}, {CC"getTimeStamp", CC"()J", FN_PTR(getTimeStamp)}, - {CC"getNextStackFrame", CC"("HS_STACK_FRAME_REF HS_RESOLVED_METHOD")"HS_STACK_FRAME_REF, FN_PTR(getNextStackFrame)}, + {CC"getNextStackFrame", CC"("HS_STACK_FRAME_REF "[JI)"HS_STACK_FRAME_REF, FN_PTR(getNextStackFrame)}, {CC"materializeVirtualObjects", CC"("HS_STACK_FRAME_REF"Z)V", FN_PTR(materializeVirtualObjects)}, }; diff -r 3dde8d8c95b8 -r 40d0022115ee src/share/vm/graal/graalEnv.cpp --- a/src/share/vm/graal/graalEnv.cpp Fri Apr 25 16:21:07 2014 +0200 +++ b/src/share/vm/graal/graalEnv.cpp Mon Apr 28 11:18:15 2014 +0200 @@ -515,7 +515,7 @@ // (Put nm into the task handle *before* publishing to the Java heap.) if (task != NULL) task->set_code(nm); - if (HotSpotNmethod::isDefault(installed_code())) { + if (installed_code->is_a(HotSpotNmethod::klass()) && HotSpotNmethod::isDefault(installed_code())) { if (entry_bci == InvocationEntryBci) { if (TieredCompilation) { // If there is an old version we're done with it diff -r 3dde8d8c95b8 -r 40d0022115ee src/share/vm/graal/graalGlobals.hpp --- a/src/share/vm/graal/graalGlobals.hpp Fri Apr 25 16:21:07 2014 +0200 +++ b/src/share/vm/graal/graalGlobals.hpp Mon Apr 28 11:18:15 2014 +0200 @@ -52,6 +52,9 @@ COMPILERGRAAL_PRESENT(product(bool, BootstrapGraal, true, \ "Bootstrap Graal before running Java main method")) \ \ + product(bool, ForceGraalInitialization, false, \ + "Force VM to initialize the Compiler although not used") \ + \ product(intx, TraceGraal, 0, \ "Trace level for Graal") \ \ @@ -88,6 +91,9 @@ product(bool, UseHSAILDeoptimization, true, \ "Code gen and runtime support for deoptimizing HSAIL kernels") \ \ + product(bool, UseHSAILSafepoints, true, \ + "Code gen and runtime support for safepoints in HSAIL kernels") \ + \ product(bool, GPUOffload, false, \ "Offload execution to GPU whenever possible") \ \ diff -r 3dde8d8c95b8 -r 40d0022115ee src/share/vm/graal/graalJavaAccess.cpp --- a/src/share/vm/graal/graalJavaAccess.cpp Fri Apr 25 16:21:07 2014 +0200 +++ b/src/share/vm/graal/graalJavaAccess.cpp Mon Apr 28 11:18:15 2014 +0200 @@ -59,11 +59,12 @@ #define FLOAT_FIELD(klass, name) FIELD(klass, name, "F", false) #define OOP_FIELD(klass, name, signature) FIELD(klass, name, signature, false) #define STATIC_OOP_FIELD(klass, name, signature) FIELD(klass, name, signature, true) +#define STATIC_INT_FIELD(klass, name) FIELD(klass, name, "I", true) void graal_compute_offsets() { - COMPILER_CLASSES_DO(START_CLASS, END_CLASS, CHAR_FIELD, INT_FIELD, BOOLEAN_FIELD, LONG_FIELD, FLOAT_FIELD, OOP_FIELD, STATIC_OOP_FIELD) - guarantee(HotSpotInstalledCode::_codeBlob_offset == sizeof(oopDesc), "codeBlob must be first field!"); + COMPILER_CLASSES_DO(START_CLASS, END_CLASS, CHAR_FIELD, INT_FIELD, BOOLEAN_FIELD, LONG_FIELD, FLOAT_FIELD, OOP_FIELD, STATIC_OOP_FIELD, STATIC_INT_FIELD) + guarantee(InstalledCode::_address_offset == sizeof(oopDesc), "codeBlob must be first field!"); } #define EMPTY0 @@ -72,7 +73,7 @@ #define FIELD2(klass, name) int klass::_##name##_offset = 0; #define FIELD3(klass, name, sig) FIELD2(klass, name) -COMPILER_CLASSES_DO(EMPTY1, EMPTY0, FIELD2, FIELD2, FIELD2, FIELD2, FIELD2, FIELD3, FIELD3) +COMPILER_CLASSES_DO(EMPTY1, EMPTY0, FIELD2, FIELD2, FIELD2, FIELD2, FIELD2, FIELD3, FIELD3, FIELD2) diff -r 3dde8d8c95b8 -r 40d0022115ee src/share/vm/graal/graalJavaAccess.hpp --- a/src/share/vm/graal/graalJavaAccess.hpp Fri Apr 25 16:21:07 2014 +0200 +++ b/src/share/vm/graal/graalJavaAccess.hpp Mon Apr 28 11:18:15 2014 +0200 @@ -47,9 +47,9 @@ * */ -#define COMPILER_CLASSES_DO(start_class, end_class, char_field, int_field, boolean_field, long_field, float_field, oop_field, static_oop_field) \ +#define COMPILER_CLASSES_DO(start_class, end_class, char_field, int_field, boolean_field, long_field, float_field, oop_field, static_oop_field, static_int_field) \ start_class(HotSpotResolvedObjectType) \ - oop_field(HotSpotResolvedObjectType, javaClass, "Ljava/lang/Class;") \ + oop_field(HotSpotResolvedObjectType, javaClass, "Ljava/lang/Class;") \ end_class \ start_class(HotSpotResolvedJavaMethod) \ oop_field(HotSpotResolvedJavaMethod, name, "Ljava/lang/String;") \ @@ -59,8 +59,11 @@ start_class(HotSpotJavaType) \ oop_field(HotSpotJavaType, name, "Ljava/lang/String;") \ end_class \ + start_class(InstalledCode) \ + long_field(InstalledCode, address) \ + long_field(InstalledCode, version) \ + end_class \ start_class(HotSpotInstalledCode) \ - long_field(HotSpotInstalledCode, codeBlob) \ int_field(HotSpotInstalledCode, size) \ long_field(HotSpotInstalledCode, codeStart) \ int_field(HotSpotInstalledCode, codeSize) \ @@ -113,7 +116,7 @@ long_field(ExternalCompilationResult, entryPoint) \ end_class \ start_class(CompilationResult) \ - int_field(CompilationResult, frameSize) \ + int_field(CompilationResult, totalFrameSize) \ int_field(CompilationResult, customStackAreaOffset) \ oop_field(CompilationResult, targetCode, "[B") \ oop_field(CompilationResult, assumptions, "Lcom/oracle/graal/api/code/Assumptions;") \ @@ -193,6 +196,7 @@ int_field(BytecodeFrame, numLocks) \ boolean_field(BytecodeFrame, rethrowException) \ boolean_field(BytecodeFrame, duringCall) \ + static_int_field(BytecodeFrame, BEFORE_BCI) \ end_class \ start_class(BytecodePosition) \ oop_field(BytecodePosition, caller, "Lcom/oracle/graal/api/code/BytecodePosition;") \ @@ -310,7 +314,19 @@ oop_store((oop*)addr, x); \ } \ } -COMPILER_CLASSES_DO(START_CLASS, END_CLASS, CHAR_FIELD, INT_FIELD, BOOLEAN_FIELD, LONG_FIELD, FLOAT_FIELD, OOP_FIELD, STATIC_OOP_FIELD) +#define STATIC_INT_FIELD(klassName, name) \ + static int _##name##_offset; \ + static int name() { \ + InstanceKlass* ik = InstanceKlass::cast(klassName::klass()); \ + address addr = ik->static_field_addr(_##name##_offset - InstanceMirrorKlass::offset_of_static_fields()); \ + return *((jint *)addr); \ + } \ + static void set_##name(int x) { \ + InstanceKlass* ik = InstanceKlass::cast(klassName::klass()); \ + address addr = ik->static_field_addr(_##name##_offset - InstanceMirrorKlass::offset_of_static_fields()); \ + *((jint *)addr) = x; \ + } +COMPILER_CLASSES_DO(START_CLASS, END_CLASS, CHAR_FIELD, INT_FIELD, BOOLEAN_FIELD, LONG_FIELD, FLOAT_FIELD, OOP_FIELD, STATIC_OOP_FIELD, STATIC_INT_FIELD) #undef START_CLASS #undef END_CLASS #undef FIELD @@ -321,6 +337,7 @@ #undef FLOAT_FIELD #undef OOP_FIELD #undef STATIC_OOP_FIELD +#undef STATIC_INT_FIELD void compute_offset(int &dest_offset, Klass* klass, const char* name, const char* signature, bool static_field); diff -r 3dde8d8c95b8 -r 40d0022115ee src/share/vm/graal/graalVMToCompiler.cpp --- a/src/share/vm/graal/graalVMToCompiler.cpp Fri Apr 25 16:21:07 2014 +0200 +++ b/src/share/vm/graal/graalVMToCompiler.cpp Mon Apr 28 11:18:15 2014 +0200 @@ -144,15 +144,13 @@ } } -void VMToCompiler::startCompiler(jboolean bootstrap_enabled, jboolean hosted_only) { +void VMToCompiler::startCompiler(jboolean bootstrap_enabled) { JavaThread* THREAD = JavaThread::current(); JavaValue result(T_VOID); JavaCallArguments args; args.push_oop(instance()); args.push_int(bootstrap_enabled); - args.push_int(hosted_only); - TempNewSymbol bool_bool_void = SymbolTable::new_symbol("(ZZ)V", CHECK); - JavaCalls::call_interface(&result, vmToCompilerKlass(), vmSymbols::startCompiler_name(), bool_bool_void, &args, THREAD); + JavaCalls::call_interface(&result, vmToCompilerKlass(), vmSymbols::startCompiler_name(), vmSymbols::bool_void_signature(), &args, THREAD); check_pending_exception("Error while calling startCompiler"); } diff -r 3dde8d8c95b8 -r 40d0022115ee src/share/vm/graal/graalVMToCompiler.hpp --- a/src/share/vm/graal/graalVMToCompiler.hpp Fri Apr 25 16:21:07 2014 +0200 +++ b/src/share/vm/graal/graalVMToCompiler.hpp Mon Apr 28 11:18:15 2014 +0200 @@ -66,8 +66,8 @@ // public abstract void shutdownCompiler(); static void shutdownCompiler(); - // public abstract void startCompiler(boolean bootstrapEnabled, boolean hostedOnly); - static void startCompiler(jboolean bootstrap_enabled, jboolean hosted_only); + // public abstract void startCompiler(boolean bootstrapEnabled); + static void startCompiler(jboolean bootstrap_enabled); // public abstract void bootstrap(); static void bootstrap(); diff -r 3dde8d8c95b8 -r 40d0022115ee src/share/vm/oops/instanceKlass.cpp --- a/src/share/vm/oops/instanceKlass.cpp Fri Apr 25 16:21:07 2014 +0200 +++ b/src/share/vm/oops/instanceKlass.cpp Mon Apr 28 11:18:15 2014 +0200 @@ -1201,6 +1201,21 @@ JavaValue result(T_VOID); JavaCalls::call(&result, h_method, &args, CHECK); // Static call (no args) } + +#ifdef GRAAL + if (this_oop->is_subtype_of(SystemDictionary::Node_klass())) { + if (this_oop() != SystemDictionary::Node_klass()) { + // Create the NodeClass for a Node subclass. + TempNewSymbol sig = SymbolTable::new_symbol("(Ljava/lang/Class;)Lcom/oracle/graal/graph/NodeClass;", CHECK); + JavaValue result(T_OBJECT); + JavaCalls::call_static(&result, SystemDictionary::NodeClass_klass(), vmSymbols::get_name(), sig, this_oop->java_mirror(), CHECK); + this_oop->set_graal_node_class((oop) result.get_jobject()); + } else { + // A NodeClass cannot be created for Node due to checks in + // NodeClass.FieldScanner.scanField() + } + } +#endif } diff -r 3dde8d8c95b8 -r 40d0022115ee src/share/vm/prims/jni.cpp --- a/src/share/vm/prims/jni.cpp Fri Apr 25 16:21:07 2014 +0200 +++ b/src/share/vm/prims/jni.cpp Mon Apr 28 11:18:15 2014 +0200 @@ -5176,6 +5176,9 @@ #ifdef GRAAL // GraalCompiler needs to have been created in compileBroker.cpp GraalCompiler* graal_compiler = GraalCompiler::instance(); + if (ForceGraalInitialization && graal_compiler == NULL) { + graal_compiler = new GraalCompiler(); + } if (graal_compiler != NULL) { graal_compiler->initialize(); } else { diff -r 3dde8d8c95b8 -r 40d0022115ee src/share/vm/runtime/deoptimization.cpp --- a/src/share/vm/runtime/deoptimization.cpp Fri Apr 25 16:21:07 2014 +0200 +++ b/src/share/vm/runtime/deoptimization.cpp Mon Apr 28 11:18:15 2014 +0200 @@ -357,7 +357,10 @@ unpack_sp = deoptee.unextended_sp(); #ifdef ASSERT - assert(cb->is_deoptimization_stub() || cb->is_uncommon_trap_stub(), "just checking"); + assert(cb->is_deoptimization_stub() || + cb->is_uncommon_trap_stub() || + strcmp("Stub", cb->name()) == 0, + err_msg("unexpected code blob: %s", cb->name())); #endif #else intptr_t* unpack_sp = stub_frame.sender(&dummy_map).unextended_sp(); @@ -1482,7 +1485,10 @@ #ifdef GRAAL oop installedCode = nm->graal_installed_code(); if (installedCode != NULL) { - oop installedCodeName = HotSpotNmethod::name(installedCode); + oop installedCodeName = NULL; + if (installedCode->is_a(HotSpotNmethod::klass())) { + installedCodeName = HotSpotNmethod::name(installedCode); + } if (installedCodeName != NULL) { tty->print(" (Graal: installedCodeName=%s) ", java_lang_String::as_utf8_string(installedCodeName)); } else { diff -r 3dde8d8c95b8 -r 40d0022115ee src/share/vm/runtime/gpu.cpp --- a/src/share/vm/runtime/gpu.cpp Fri Apr 25 16:21:07 2014 +0200 +++ b/src/share/vm/runtime/gpu.cpp Mon Apr 28 11:18:15 2014 +0200 @@ -26,11 +26,24 @@ #include "runtime/gpu.hpp" #include "runtime/handles.hpp" -int gpu::_initialized_gpus = 0; +int Gpu::_initialized_gpus_count = 0; +Gpu* Gpu::_initialized_gpus[MAX_GPUS]; -void gpu::initialized_gpu(const char* name) { - _initialized_gpus++; - if (TraceGPUInteraction) { - tty->print_cr("[GPU] registered initialization of %s (total initialized: %d)", name, _initialized_gpus); +void Gpu::initialized_gpu(Gpu* gpu) { + // GPUs are always initialized on the same thread so no need for locking + guarantee(_initialized_gpus_count < MAX_GPUS, "oob"); + _initialized_gpus[_initialized_gpus_count++] = gpu; + if (TraceGPUInteraction) { + tty->print_cr("[GPU] registered initialization of %s (total initialized: %d)", gpu->name(), _initialized_gpus_count); + } +} + +void Gpu::safepoint_event(SafepointEvent event) { + for (int i = 0; i < _initialized_gpus_count; i++) { + if (event == SafepointBegin) { + _initialized_gpus[i]->notice_safepoints(); + } else { + _initialized_gpus[i]->ignore_safepoints(); } + } } diff -r 3dde8d8c95b8 -r 40d0022115ee src/share/vm/runtime/gpu.hpp --- a/src/share/vm/runtime/gpu.hpp Fri Apr 25 16:21:07 2014 +0200 +++ b/src/share/vm/runtime/gpu.hpp Mon Apr 28 11:18:15 2014 +0200 @@ -29,21 +29,41 @@ #include "oops/symbol.hpp" #include "utilities/array.hpp" +#define MAX_GPUS 2 + // Defines the interface to the graphics processor(s). -class gpu : AllStatic { +class Gpu : public CHeapObj { private: - static int _initialized_gpus; // number of initialize GPU devices + static int _initialized_gpus_count; + static Gpu* _initialized_gpus[MAX_GPUS]; public: // Notification of a GPU device that has been initialized. - static void initialized_gpu(const char* name); + static void initialized_gpu(Gpu* gpu); // Gets a comma separated list of supported GPU architecture names. static jobject probe_gpus(JNIEnv* env); // Gets the number of GPU devices that have been initialized. - static int initialized_gpus() { return _initialized_gpus; } + static int initialized_gpus() { return _initialized_gpus_count; } + + enum SafepointEvent { + SafepointBegin, + SafepointEnd + }; + + // Called when a safepoint has been activated. + static void safepoint_event(SafepointEvent event); + + // Name of this GPU + virtual const char* name() = 0; + + // Called when a safepoint has been activated. + virtual void notice_safepoints() {}; + + // Called when a safepoint has been deactivated. + virtual void ignore_safepoints() {}; }; #endif // SHARE_VM_RUNTIME_GPU_HPP diff -r 3dde8d8c95b8 -r 40d0022115ee src/share/vm/runtime/javaCalls.cpp --- a/src/share/vm/runtime/javaCalls.cpp Fri Apr 25 16:21:07 2014 +0200 +++ b/src/share/vm/runtime/javaCalls.cpp Mon Apr 28 11:18:15 2014 +0200 @@ -412,7 +412,7 @@ if (nm->is_alive()) { ((JavaThread*) THREAD)->set_graal_alternate_call_target(nm->verified_entry_point()); oop graalInstalledCode = nm->graal_installed_code(); - if (graalInstalledCode != NULL && HotSpotNmethod::isExternal(graalInstalledCode)) { + if (graalInstalledCode != NULL && graalInstalledCode->is_a(HotSpotNmethod::klass()) && HotSpotNmethod::isExternal(graalInstalledCode)) { entry_point = GraalCompiler::instance()->get_external_deopt_i2c_entry(); } else { entry_point = method->adapter()->get_i2c_entry(); diff -r 3dde8d8c95b8 -r 40d0022115ee src/share/vm/runtime/safepoint.cpp --- a/src/share/vm/runtime/safepoint.cpp Fri Apr 25 16:21:07 2014 +0200 +++ b/src/share/vm/runtime/safepoint.cpp Mon Apr 28 11:18:15 2014 +0200 @@ -39,6 +39,7 @@ #include "runtime/compilationPolicy.hpp" #include "runtime/deoptimization.hpp" #include "runtime/frame.inline.hpp" +#include "runtime/gpu.hpp" #include "runtime/interfaceSupport.hpp" #include "runtime/mutexLocker.hpp" #include "runtime/osThread.hpp" @@ -205,6 +206,12 @@ os::make_polling_page_unreadable(); } +#ifdef GRAAL + if (UseHSAILSafepoints) { + Gpu::safepoint_event(Gpu::SafepointBegin); + } +#endif + // Consider using active_processor_count() ... but that call is expensive. int ncpus = os::processor_count() ; @@ -438,6 +445,12 @@ // Remove safepoint check from interpreter Interpreter::ignore_safepoints(); +#ifdef GRAAL + if (UseHSAILSafepoints) { + Gpu::safepoint_event(Gpu::SafepointEnd); + } +#endif + { MutexLocker mu(Safepoint_lock); diff -r 3dde8d8c95b8 -r 40d0022115ee src/share/vm/runtime/thread.cpp --- a/src/share/vm/runtime/thread.cpp Fri Apr 25 16:21:07 2014 +0200 +++ b/src/share/vm/runtime/thread.cpp Mon Apr 28 11:18:15 2014 +0200 @@ -1680,9 +1680,11 @@ if (_thread_stat != NULL) delete _thread_stat; #ifdef GRAAL - if (GraalCounterSize > 0 && graal_counters_include(threadObj())) { - for (int i = 0; i < GraalCounterSize; i++) { - _graal_old_thread_counters[i] += _graal_counters[i]; + if (GraalCounterSize > 0) { + if (graal_counters_include(threadObj())) { + for (int i = 0; i < GraalCounterSize; i++) { + _graal_old_thread_counters[i] += _graal_counters[i]; + } } FREE_C_HEAP_ARRAY(jlong, _graal_counters, mtInternal); } diff -r 3dde8d8c95b8 -r 40d0022115ee src/share/vm/runtime/vmStructs.cpp --- a/src/share/vm/runtime/vmStructs.cpp Fri Apr 25 16:21:07 2014 +0200 +++ b/src/share/vm/runtime/vmStructs.cpp Mon Apr 28 11:18:15 2014 +0200 @@ -576,6 +576,7 @@ nonstatic_field(ThreadLocalAllocBuffer, _start, HeapWord*) \ nonstatic_field(ThreadLocalAllocBuffer, _top, HeapWord*) \ nonstatic_field(ThreadLocalAllocBuffer, _end, HeapWord*) \ + nonstatic_field(ThreadLocalAllocBuffer, _pf_top, HeapWord*) \ nonstatic_field(ThreadLocalAllocBuffer, _desired_size, size_t) \ nonstatic_field(ThreadLocalAllocBuffer, _refill_waste_limit, size_t) \ static_field(ThreadLocalAllocBuffer, _target_refills, unsigned) \ @@ -2422,6 +2423,7 @@ declare_constant(Method::_force_inline) \ declare_constant(Method::_dont_inline) \ declare_constant(Method::_hidden) \ + declare_constant(Method::nonvirtual_vtable_index) \ \ declare_constant(ConstMethod::_has_linenumber_table) \ declare_constant(ConstMethod::_has_checked_exceptions) \ diff -r 3dde8d8c95b8 -r 40d0022115ee test/whitelist_baseline.txt --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/whitelist_baseline.txt Mon Apr 28 11:18:15 2014 +0200 @@ -0,0 +1,19 @@ +# com.oracle.graal.jtt.loop.Loop03 +# com.oracle.graal.jtt.loop.Loop04 +# com.oracle.graal.jtt.loop.Loop08 +# com.oracle.graal.jtt.loop.Loop11 +com.oracle.graal.jtt.bytecode.BC_iadd +com.oracle.graal.jtt.bytecode.BC_iadd2 +com.oracle.graal.jtt.bytecode.BC_iadd3 +com.oracle.graal.jtt.bytecode.BC_ifeq_2 +com.oracle.graal.jtt.bytecode.BC_ifeq_3 +com.oracle.graal.jtt.bytecode.BC_ifeq +com.oracle.graal.jtt.bytecode.BC_aload_3 +com.oracle.graal.jtt.bytecode.BC_aload_2 +com.oracle.graal.jtt.bytecode.BC_aload_1 +com.oracle.graal.jtt.bytecode.BC_aload_0 +com.oracle.graal.jtt.bytecode.BC_areturn +com.oracle.graal.jtt.bytecode.BC_freturn +com.oracle.graal.jtt.bytecode.BC_iconst +com.oracle.graal.jtt.bytecode.BC_ireturn +com.oracle.graal.jtt.bytecode.BC_lreturn diff -r 3dde8d8c95b8 -r 40d0022115ee test/whitelist_shortunittest.txt --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/whitelist_shortunittest.txt Mon Apr 28 11:18:15 2014 +0200 @@ -0,0 +1,1 @@ +com.oracle.graal.jtt.bytecode.*